ASP.NET Core - Teil 1: die Basics

ASP.NET Core - Teil 1: die Basics

Seit Ende Juni steht ASP.NET Core 1 als RTM zur Verfügung - und es erfreut sich großer Beliebtheit!

In diesem mehrteiligen Beitrag möchte ich einen Einstieg für Interessierte bieten.

Die Plattformunabhängigkeit

Anders als seine Vorgänger ist ASP.NET Core nicht nur auf Windows Zuhause, sondern auch auf Linux und dem macOS. Auch Docker, das - zurecht - derzeit besonders hohe Belebtheit erfährt, wird voll unterstützt.

Eigener Webserver Kestrel

ASP.NET wurde von Haus aus auf dem IIS betrieben. ASP.NET Core hat seinen eigenen Webserver: Kestrel. Kestrel wird hierbei durch ein NuGet Paket mitgeliefert und wirkt als ein Reverse Proxy. Anfragen gehen also zuerst auf einen nativen Webserver wie nginx, IIS oder Apache, anschließend zu Kestrel und werden dann von ASP.NET Core verarbeitet.

{
  "buildOptions": {
    "emitEntryPoint": true
  },
  "dependencies": {
    "Microsoft.NETCore.App": {
      "type": "platform",
      "version": "1.0.0"
    },
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0"
  },
  "frameworks": {
    "netcoreapp1.0": {}
  }
}

Das hört sich erstmal kompliziert an; führt aber dazu, dass die gesamte Anwendung um ein vielfaches Performanter läuft und ASP.NET Core nur Kestrel selbst kennen muss.

Console Application

ASP.NET Core ist nur noch eine Konsolenanwendung.

using System;
using Microsoft.AspNetCore.Hosting;

namespace ASPNETCore
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseKestrel()
                .UseStartup<Startup>()
                .Build();

            host.Run();
        }
    }
}

Diese wenigen Zeilen bilden bereits eine vollständig lauffähige ASP.NET Core Webanwendung.

Der WebHostBuilder erstellt dabei den Host der Webanwendung. Neben der Registrierung von Kestrel wird hierbei eine Startup-Klasse referenziert.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
    }

    public void Configure(IApplicationBuilder app)
    {
    }
}

Die Startup-Klasse ist dazu da, dass initiale Dinge wie Services oder Applikationseinstellungen global registriert bzw. hinterlegt werden können. Configure ist hierbei dazu da, dass verschiedene und beliebig viele Middleware-Implementierungen angegeben werden können.

Dependency Injection

ASP.NET Core hat seine eigene Dependency Injection-Implementierung. Sie ähnelt stark Unity; wobei auch andere Inversion of Control Container wie NInject verwendet werden können.

Services

Die eingebaute Dependency Injection wird als Basis genommen, um Services in ASP.NET Core zu registrieren. Services sind hierbei zB. DbContext-Implementierungen wie vom SQL Server zB. auf Basis des Entity Framwork Core 1 oder auch Identity Provider für die Authentifizierung.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("MyConnectionString")));

Middleware

Middlewares werden über Startup.Configure der ASP.NET Core 1 Pipeline hinzugefügt. Jeder Request, der ASP.NET Core 1 erreicht, wird durch diese Pipeline geschickt und damit von den registrierten Middleware-Implementierungen verarbeitet.

Zum Beispiel ist die Verarbeitung von URLs im Sinne von Routen eine Middleware.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory lf)
{
    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

Hello world

Ein vollständig, simples Beispiel zu Hello World mit ASP.NET Core 1 seht ihr hier:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace AspNetCore_Basics_HelloWorld
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseKestrel()
                .UseStartup<Startup>()
                .Build();

            host.Run();
        }
    }

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
        }
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory lf)
        {
            loggerFactory.AddConsole();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Hello World!");
            });
        }
    }
}