ASP.Net Core application from scratch

Asp.Net Core is a toolset for creating web applications for .Net Core. Although the name contains ASP.Net this is an absolutely new product for web-developers.

It is simple and clear and it allows you to write more compact code. Web applications created with Asp.Net Core are cross platform and can be ran without IIS (Internet Information Server) and Azure (but can work with them too).

Lets stop talking and create a simple ASP.Net Core application without from scratch. We will not use any code generators (like yeoman) nor any IDE. No ugly web.config files. Even Windows is not required (but can be used). Only terminal and your favorite text editor. .Net Core SDK should be pre-installed too of cause.

Create new .Net Core console application in empty directory by command

dotnet new -T Console

Open the created file project.json and add to field dependencies next values:

In project.json

{
   "Microsoft.NETCore.App": {
      "version": "1.0.0",
      "type": "platform"
    },
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0"
}

The first line will add Asp.Net Core support to our application. The second line will allow the web application to be self-hosted (with Kestrel web server).

From Command line Run:

dotnet restore

That will install ASP.Net core packages.

Copy/Paste into Program.cs

using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Builder;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseKestrel() // use self-hosted web server
                .UseStartup()
                .Build();

            host.Run();
        }
    }

    public class Startup
    {
        public void Configure()
        {
        }
    }
}

From Command line Run:

dotnet run

Hooray, we did it! Open browser to: http://localhost:5000 and see … nothing.

Let’s make our web application show some text.

Program.cs

using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;

namespace ConsoleApplication
{
    public class Program { /* unchanged */ }

    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            // We'll add own middleware
            app.Use(async (context, next) => {
                await next.Invoke(); // call other chained middlewares
                await context.Response.WriteAsync("Hello ASP.Net Core");
            });
    // If you work with express or koa in nodejs or sinatra in ruby you will see a lot of similar stuffs here
        }
    }

}

Run the application again. Good. Now we can see text “Hello ASP.Net Core” in the browser.

MVC

Let’s make our application more complex. First add MVC support. Open project.json and add into dependencies line

"Microsoft.AspNetCore.Mvc": "1.0.0"

Run

 dotnet restore

to install ASP.Net MVC libraries.

Now change class Startup

public void ConfigureServices(IServiceCollection services)
{
    // This method is used to register services to use them via Dependency Injection in other parts of code.
    services.AddMvc();
}

public void Configure(IApplicationBuilder app)
{
    app.UseMvc();
}

Now our application is MVC-powered.

Lets create a controller. Create directory controllers and add file DemoController.cs there with content

DemoController.cs

using Microsoft.AspNetCore.Mvc;

namespace ConsoleApplication.Controllers
{
    [Route("[controller]")]
    public class DemoController : Controller
    {

        // GET /demo
        [HttpGet]
        public string Index()
        {
            return "Hello ASP.Net Core";
        }

    }
}

Attribute [Route("[controller]")] says that our controller will handle routes with pathes /demo (demo is taken from name of DemoController).

Lets run our application and make GET request to http://localhost:5000/demo. We will see text “Hello ASP.Net Core”.

Let’s make this action a bit more async.

In DemoController.cs

// GET /demo
[HttpGet]
public async Task Index()
{
    // call any async methods with `await` here
    return Task.FromResult("Hello ASP.Net Core");
}

Ok, let’s make action which can extract query parameters from request. Add next method to DemoController.

In DemoController.cs

// GET /demo/query
[HttpGet("query")]
public string Query([FromQuery] string text)
{
   return $"Your query string is \"{text}\"";
}

Run the application and make GET request to http://localhost:5000/demo/query?text=hello to see result. Replace [FromQuery] by [FromQuery(Name="q")]. Now our application will handle GET requests like http://localhost:5000/demo/query?q=hello.

Lets extract parameter from request url. Add next method

In DemoController.cs

// GET /demo/{id}
[HttpGet("{id}")]
public string Get(string id)
{
    return $"Item {id}";
}

Now we can make GET requests like /demo/123.

What about posting form data? Lets add this method.

In DemoController.cs

// POST /demo
[HttpPost]
public IActionResult Create([FromForm] Item item)
{
    return Created("http://localhost/demo/id", item);
}

where Item is

public class Item
{
    public string Text {get; set;}
}

Re-run the application and make POST request to /demo with form (application/x-www-form-urlencoded) text=hello. If you omit field text in such request the property Text of item in method Create() will be null.

Lets handle json data. Replace [FromForm] in method Create by [FromBody]. Now make POST request to /demo with json content {"Text": "hello"} You will see same result.
But if we post in json field text instead of Text the item.Text will be null. Lets fix that. Open Program.cs and change ConfigureServices of StartUp by

In Program.cs

services
  .AddMvc()
  .AddJsonOptions(s => s.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver());

Now our app will work with camel-cased names in json data right.

Dependency injection

Dependency injection is a technique for achieving loose coupling between objects and their collaborators, or dependencies. Rather than directly instantiating collaborators, or using static references. The objects a class needs in order to perform its actions are provided to the class in some fashion. ASP.Net Core has support of dependency injection in the box. Lets see how it works.

Lets add a “useful” service

public interface IMyUsefullService{
 void Run();
}

public class MyUsefullService : IMyUsefullService
{
    public void Run()
    {
        //TODO do something
    }
}

Now register our service in ConfigureServices of Startup by line

services.AddTransient<IMyUsefullService, MyUsefullService>();

Thats all. Now we can use instance of IMyUsefullService in constructor of any our controller and instance of MyUsefullService will be used there.

public class DemoController : Controller
{
    private readonly IMyUsefullService _myUsefullService;
    // Constructor
    public DemoController (IMyUsefullService myUsefullService)
    {
      if(myUsefullService == null)
      {
          throw new ArgumentNullException(nameof(myUsefullService));
      }
      _myUsefullService = myUsefullService;
      // now we can use _myUsefullService in any action of this controller
      // instance of MyUsefullService will be stored in this field but the controller doesn't know about that
    }
}

Here we showed a small piece of ASP.Net Core infrastructure. The basis of any ASP.Net Core application is small kernel which includes middleware, dependency injection, logging, configuration, and error handling support. Other possibilities (like MVC, Views, Databases, etc supports) are implemented as external libraries.

You can use only things you explicitly require. Each such library extends web application by new middlewares (their registering code is often hidden in extension methods of IApplicationBuilder) and services (like database context). You can split your own code to middlewares and share it with different applications.

Say hello to more compact and clear code of web applications in .Net Core universe. Start to use ASP.Net Core in new projects.