Now that .NET Core 2.0 and ASP.NET Core 2.0 have been released, I am going to update all the existing samples over time. All the new samples will rely on ASP.NET Core 2.0 immediately.
If you are studying ASP.NET Core, I am lurking on this Gitter Channel.
The goal of this project is to enable .NET programmers to learn the new ASP.NET Core stack from the ground up directly from code. I will not address ASP.NET Core MVC in this project. There is so much power in the underlying ASP.NET Core stack. Don't miss them!
You should download the latest release version .NET Core SDK to be able to run these samples.
If you are running these samples on Linux, change the target framework inside the csproj files from
<TargetFramework>net461</TargetFramework>
to
<TargetFramework>netcoreapp1.1</TargetFramework>
or to
<TargetFramework>netcoreapp2.0</TargetFramework>
Every sample is designed specifically to demonstrate a single idea. We will go wide and deep to the nitty gritty of ASP.NET Core stack. Enjoy the ride!
Some of the samples you see here involve mixed projects (net461) that will run only in Windows. For many .NET developers, full framework is the reality for forseeable future. We are not going to port multi-year production systems to run on Linux. We want to improve the creaky .NET MVC 2.0 that we have lying around and bring it up to speed to aspnetcore MVC.
If a sample requires additional dependencies, I will list them.
I highly recommend using Visual Studio Code to play around with these samples but it is not required. You can use Visual Studio 2017 as well.
To run these samples, simply open your command line console, go to each folder and execute dotnet restore
and then continue with dotnet watch run
.
This is a good explanation on what's new on ASP.NET Core 2.0. If you are new to ASP.NET Core, skip this section and go through the examples of ASP.NET Core 1.1/2.0 Samples
listed below. They are better organized for newcomers.
This section will show new things in ASP.NET Core 2.0. The rest of the samples will work in ASP.NET Core 1.1 unless specified otherwise.
-
Hello World with Microsoft.AspNetCore.All package
If you are targeting
netcoreapp2.0
, you can useMicrosoft.AspNetCore.All
meta package that download most of the necessary packages to develop an ASP.NET Core/MVC system (including EF DB support).It also adds the following packages
Installing Microsoft.IdentityModel.Logging 1.1.4. Installing Microsoft.IdentityModel.Tokens 5.1.4. Installing runtime.win-x64.runtime.native.System.Data.SqlClient.sni 4.4.0. Installing runtime.win-x86.runtime.native.System.Data.SqlClient.sni 4.4.0. Installing runtime.win-arm64.runtime.native.System.Data.SqlClient.sni 4.4.0. Installing System.IdentityModel.Tokens.Jwt 5.1.4. Installing System.Text.Encoding.CodePages 4.4.0. Installing runtime.native.System.Data.SqlClient.sni 4.4.0. Installing Microsoft.Azure.KeyVault.WebKey 2.0.7. Installing Microsoft.Rest.ClientRuntime.Azure 3.3.7. Installing Microsoft.Rest.ClientRuntime 2.3.8. Installing SQLitePCLRaw.lib.e_sqlite3.v110_xp 1.1.7. Installing SQLitePCLRaw.lib.e_sqlite3.linux 1.1.7. Installing SQLitePCLRaw.lib.e_sqlite3.osx 1.1.7. Installing SQLitePCLRaw.provider.e_sqlite3.netstandard11 1.1.7. Installing Microsoft.IdentityModel.Protocols 2.1.4. Installing Microsoft.NETCore.App 2.0.0-preview2-25407-01. Installing Microsoft.NETCore.DotNetHostPolicy 2.0.0-preview2-25407-01. Installing Microsoft.NETCore.Platforms 2.0.0-preview2-25405-01. Installing NETStandard.Library 2.0.0-preview2-25401-01. Installing Microsoft.NETCore.DotNetHostResolver 2.0.0-preview2-25407-01. Installing Microsoft.Packaging.Tools 1.0.0-preview2-25401-01. Installing System.Interactive.Async 3.1.1. Installing SQLitePCLRaw.core 1.1.7. Installing Microsoft.IdentityModel.Protocols.OpenIdConnect 2.1.4. Installing SQLitePCLRaw.bundle_green 1.1.7. Installing Microsoft.Azure.KeyVault 2.3.2. Installing Microsoft.IdentityModel.Clients.ActiveDirectory 3.14.1. Installing WindowsAzure.Storage 8.1.4. Installing System.Data.SqlClient 4.4.0. Installing Microsoft.NETCore.DotNetAppHost 2.0.0-preview2-25407-01.
In ASP.NET Core 2.0, this is the recommended way to start your host
public class Program { public static void Main(string[] args) { BuildWebHost(args).Run(); } public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .UseEnvironment("Development") .Build(); }
-
A new way of configuring logging
Now you configure logging at
Program
instead ofStartup.Configure
viaConfigureLogging
. -
Now you can adjust what kind of logging information from various part of ASP.NET Core and your app you want show/stored.
-
ASP.NET Core 1.1
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory logger) { //These are the three default services available at Configure app.Run(context => { return context.Response.WriteAsync('hello world'); }); }
ASP.NET Core 2.0
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory logger, IConfiguration configuration) { //These are the four default services available at Configure app.Run(context => { return context.Response.WriteAsync(configuration["greeting"]); }); }
-
Session Feature with Redis using BinaryFormatter
This shows how to use session with
Redis
store. We useBinaryFormatter
which is only available at.NET Core 2.0
to serialize and deserialize your object. The better way is to serialize your object using Json - BinaryFormatter is SLOW.Make sure you have
Redis
running on yourlocalhost
at default port. The connection string is specified atappsetings.json
. -
Session Feature with Redis using JSON Serialization
This shows how to use session with
Redis
store. Use this method instead of usingBinaryFormatter
.Make sure you have
Redis
running on yourlocalhost
at default port. The connection string is specified atappsetings.json
.Note: This method is already available since ASP.NET Core 1.0. I put it here so it is located next to the
BinaryFormatter
sample. -
This exists on since .NET Core 1.0 however the configuration for the cookie has changed slightly. We are using
IAntiForgery
interface to store and generate anti forgery token to prevent XSRF/CSRF attacks. -
This is the simplest example of the brand new
Razor Pages
. It shows the two approaches toRazor Pages
, one with inline code behind and another with separate code behind. -
Compare and contrast on how the same task can be performed by using
Razor Pages
andMVC
.This sample also shows you how to us
Entity Framework Core
In-Memory Database. -
Use
app.UseRouter()
extension to create minimalistic HTTP services similar to Nancy. -
Use
app.UseRouter()
with alternative lambda signature. -
Implement background tasks using the new
IHostedService
interface.
All the samples below will run on ASP.NET Core 1.1 and ASP.NET Core 2.0.
All these projects require the following dependencies
"Microsoft.AspNetCore.Hosting" : "1.1.0-*"
-
Hello World (21)
-
Setup your most basic web app and enable the change+refresh development experience.
We are using
IApplicationBuilder Run
, an extension method for adding terminal middleware. -
Startup class
-
Hello World with startup basic
This project contains all the available services available in Startup class constructor,
ConfigureServices
andConfigure
methods. -
Hello World with custom startup class name
You don't have to call your startup class
Startup
. Any valid C# class will do. -
Hello World with responding to multiple urls
Configure so that your web app responds to multiple urls.
-
Hello World with multiple startups
This project highlights the fact that you can create multiple Startup classes and choose them at start depending on your needs.
-
Hello World with multiple startups using environment
This project highlights the fact that you can create multiple startup classes and choose them at start depending on your needs depending on your environment (You do have to name the startup class with Startup).
-
Hello World with multiple Configure methods based on environment
This project demonstrates the ability to pick
Configure
method in a single Startup class based on environment. -
Hello World with multiple ConfigureServices methods based on environment
This project demonstrates the ability to pick
ConfigureServices
method in a single Startup class based on environment. -
Hello World with an implementation of IStartup interface
We are really getting into the weed of startup right now. This is an example on how to implement
IStartup
directly. -
Hello World without a startup class
Why? just because we can.
-
Hello world with IStartupFilter
Use
IStartupFilter
to configure your middleware. This is an advanced topic. This article tries at explainingIStartupFilter
. I will add more samples soIStartupFilter
can be clearer.
-
-
Show a detailed report on exceptions that happen during the startup phase of your web app. It is very useful during development.
-
Enumerate the connection information of a HTTP request.
-
Set your application environment to
Development
orProduction
or other mode directly from code. -
Setup a basic logging in your app and show it to console.
We add the following dependencies
"Microsoft.Extensions.Logging": "1.1.0"
and"Microsoft.Extensions.Logging.Console": "1.1.0"
We are using
IApplicationBuilder Run
, an extension method for adding terminal middleware. -
Console logging - without framework log messages
Filter out frameworking logging from your log output. Without filtering, logging can get very annoying becuase the framework produces a lot of messages.
-
ASPNetCore is built on top of pipelines of functions called middleware.
We are using
IApplicationBuilder Use
, an extension method for adding middleware andIApplicationBuilder Run
. -
Respond to application startup and shutdown.
We are using
IApplicationLifetime
that trigger events during application startup and shutdown. -
IHostingEnvironment
is available atStartup
constuctor andStartup.Configure
. This sample shows all the properties available in this interface. -
Requires
Microsoft.Extensions.PlatformAbstractions" : "1.1.0-*
dependency. This sample shows how to obtain application environment information (target framework, etc). -
Demonstrate on how to add a response header and where is allowed place to do it.
-
-
Request(7)
This section shows all the different ways you capture input and examine request to your web application.
-
HTTP Verb (1)
-
Detect the verb/method of the current request.
-
-
Headers (2)
-
Enumerate all the available headers in a request.
-
Type Safe Access to Request Headers
Instead of using string to access HTTP headers, use type safe object properties to access common HTTP headers.
-
-
Form (2)
We take dependency on
"Microsoft.AspNetCore.Routing" : "1.1.0-*"
to enable routing facilities to make the form handling easier.-
Handles the values submitted via a form.
-
Upload a single file and save it to the current directory (check out the usage of
.UseContentRoot(Directory.GetCurrentDirectory())
)
-
-
Cookies (2)
-
Read and write cookies.
-
Simply demonstrates on how to remove cookies.
-
-
-
Routing (9)
We take dependency on
"Microsoft.AspNetCore.Routing" : "1.1.0-*"
to enable routing facilities in your aspnetcore apps. There are several samples to illuminate this powerful library.-
A single route handler that handles every path request.
-
Two route handler, one for home page (/) and the other takes the rest of the request using asterisk (*) in the url template.
-
We are exploring default handler - this is the entry point to create your own framework.
-
We are mixing optional route parameter, route parameter with default value and default handler.
-
[Router 5]
This is still broken. I am trying to figure out how to do nested routing. Wish me luck!
-
We are building a template route segment by segment and parts by parts, oldskool. We are using
TemplateMatcher
,TemplateSegment
andTemplatePart
.Hold your mask, we are going deep.
-
We are creating a routing template with two segments, one with Literal part and the other Parameter part, e.g, "/page/{*title}"
-
We are creating a routing template with one segment consisted of two parts, one Literal and one Parameter, e.g. "/page{*title}". Note the difference between this example and Router 7.
-
I am still trying to determine whether
TemplateMatcher
uses theInlineConstraint
information.Update: No,
TemplateMatcher
does not run constraints. #362 -
We have been building a
RouteTemplate
manually usingTemplateSegment
andTemplatePart
. In this example we are usingTemplateParser
to build theRouteTemplate
using string.
-
-
Middleware (8)
We will explore all aspect of middleware building in this section. There is no extra dependency taken other than
Kestrel
anddotnet watch
.-
This example shows how to pass information from one middleware to another using
HttpContext.Items
. -
This is the simplest middleware class you can create.
-
Use
app.Map
(MapMiddleware
) to configure your middleware pipeline to respond only on specific url path. -
Nested
app.Map
(showRequest.Path
andRequest.PathBase
). -
Use
app.MapWhen
(MapWhenMiddleware
) and Nestedapp.Map
(showRequest.Path
andRequest.PathBase
). -
Use
MapMiddleware
andMapWhenMiddleware
directly without using extensions (showRequest.Path
andRequest.PathBase
). -
Demonstrate the various ways you can inject dependency to your middleware class manually.
-
Demonstrate how to ASP.NET Core built in DI (Dependency Injection) mechanism to provide dependency for your middleware.
-
-
Features (7)
Features are collection of objects you can obtain from the framework at runtime that serve different purposes.
-
Use this Feature to obtain a list of urls that your app is responding to.
-
Obtain details of a current request. It has some similarity to HttpContext.Request. They are not equal.
HttpContext.Request
has more properties. -
Use
IHttpConnectionFeature
interface to obtain local ip/port and remote ip/port. -
Create your own custom Feature and pass it along from a middleware.
-
Shows how you can replace an implementation of a Feature with another within the request pipeline.
-
Use this feature to detect the culture of a web request through
IRequestCultureFeature
. It needs the following dependency"Microsoft.AspNetCore.Localization": "1.1.0"
. -
Use session within your middlewares. This sample shows a basic usage of in memory session. It needs the following dependency '"Microsoft.AspNetCore.Session" : "1.1.0-"
and
"Microsoft.Extensions.Caching.Memory" : "1.1.0-"`.
-
-
Dependency Injection (2)
ASP.NET Corenetcore lives and die by DI. It relies on
Microsoft.Extensions.DependencyInjection
library. There is no need to put this dependency in yourproject.json
explicitly because aspnetcore already has this package as its own dependency.-
Dependency Injection 1 - The basic
Demonstrate the three lifetime registrations for the out of the box DI functionality: singleton (one and only forever), scoped (one in every request) and transient (new everytime).
-
Dependency Injection 3 - Easy registration
Register all objects configured by classes that implements a specific interface (
IBootstrap
in this example). This is useful when you have large amount of classes in your project that needs registration. You can register them near where they are (usually in the same folder) instead of registering them somewhere in a giant registration function.Note: example 2 is forthcoming. The inspiration has not arrived yet.
-
-
File Provider (2)
We will deal with various types of file providers supported by ASP.NET Core
-
Physical File Provider - Content and Web roots
Access the file information on your Web and Content roots.
-
Implement a simple and largely nonsense file provider. It is a good starting point to implement your own proper File Provider.
-
-
In Memory Caching (a.k.a local cache) (4)
These samples depends on
Microsoft.Extensions.Caching.Memory
library. Please add this dependency to yourproject.json
.-
Caching - Absolute/Sliding expiration
This is the most basic caching you can use either by setting absolute or sliding expiration for your cache. Absolute expiration will remove your cache at a certain point in the future. Sliding expiration will remove your cache after period of inactivity.
-
Add file dependency to your caching so when the file changes, your cache expires.
You need to put the cache file in your
project.json
so it gets copied over, e.g."buildOptions": { "emitEntryPoint": true, "copyToOutput": ["cache-file.txt"] }
Note: example 1 is forthcoming. The inspiration has not arrived yet.
-
Caching 3 - Cache removal event
Register callback when a cached value is removed.
-
Caching 4 - CancellationChangeToken dependency
Bind several cache entries to a single dependency that you can reset manually.
-
-
Configuration (7)
This section is all about configuration, from memory configuration to INI, JSON and XML.
-
This is the 'hello world' of configuration. Just use a memory based configuration and read/write values to/from it.
-
Use IOptions at the most basic.
-
Configuration - Environment variables
Load environment variables and display all of them.
-
Read from INI file. It requires taking a new dependency,
"Microsoft.Extensions.Configuration.INI" : "1.1.0"
. -
Configuration - INI file - Options
Read from INI file (with nested keys) and IOptions. It requires taking two new dependencies,
"Microsoft.Extensions.Configuration.INI" : "1.1.0"
and"Microsoft.Extensions.Options.ConfigurationExtensions" : "1.1.0"
. -
Read from XML file. It requires taking a new dependency,
"Microsoft.Extensions.Configuration.Xml" : "1.1.0"
.Note: This Xml Configuration provider does not support repeated element.
The following configuration settings will break:
<appSettings> <add key="webpages:Version" value="3.0.0.0" /> <add key="webpages:Enabled" value="false" /> </appSettings>
On the other hand you can get unlimited nested elements and also attributes.
-
Configuration - XML file - Options
Read from XML file and use IOptions. It requires taking two new dependencies,
"Microsoft.Extensions.Configuration.Xml" : "1.1.0"
and"Microsoft.Extensions.Options.ConfigurationExtensions" : "1.1.0"
.
-
-
Localization and Globalization (6)
This section is all about languages, culture, etc.
-
Shows the most basic use of localization using a resource file. This sample only supports French language (because we are fancy). It needs the following dependency
"Microsoft.AspNetCore.Localization": "1.1.0"
and"Microsoft.Extensions.Localization": "1.1.0"
. -
We build upon the previous sample and demonstrate how to switch request culture via query string using the built in
QueryStringRequestCultureProvider
. This sample supports English and French. -
Demonstrate the difference between
Culture
andUI Culture
. -
Demonstrate how to switch request culture via cookie using the built in
CookieRequestCultureProvider
. This sample supports English and French. -
Demonstrate using Portable Object (PO) files to support localization instead of the cumbersome resx file. This sample requires
OrchardCore.Localization.Core
package. This sample requiresASPNET Core 2
. -
This is a continuation of previous sample but with context, which allows the same translation key to return different strings.
-
-
URL Redirect/Rewriting (6)
This section explore the dark arts of URL Rewriting
-
Shows the most basic of URL rewriting which will redirect (returns HTTP 302) anything to the home page "/". It requires
"Microsoft.AspNetCore.Rewrite" : "1.0.0-*"
and"Microsoft.AspNetCore.Routing" : "1.1.0-*"
dependencies. These two dependencies apply to the rest of the samples in this category.If you have used routing yet, I recommend of checking out the routing examples.
-
Redirect (returns HTTP 302) anything with an extension e.g. about-us.html or welcome.aspx to home page (/). It also shows how to capture the matched regex values.
-
Rewrite anything with an extension e.g. about-us.html or welcome.aspx to home page (/). It also shows how to capture the matched regex values.
-
Permanent Redirect (returns HTTP 301) anything with an extension e.g. about-us.html or welcome.aspx to home page (/). It also shows how to capture the matched regex values.
-
Implement a custom redirect logic based on
IRule
implementation. Require additional dependency of"Microsoft.AspNetCore.StaticFiles": "1.1.0"
to serve images.This custom redirection logic allows us to simply specify the image file names without worrying about their exact path e.g.'xx.jpg' and 'yy.png'.
-
Implement a custom redirect logic using lambda (similar functionality to Rewrite - 5). Require additional dependency of
"Microsoft.AspNetCore.StaticFiles": "1.1.0"
to serve images.This custom redirection logic allows us to simply specify the image file names without worrying about their exact path e.g.'xx.jpg' and 'yy.png'.
-
-
Compression (1)
Enable the ability to compress ASP.NET Core responses. These samples takes a dependency of
Microsoft.AspNetCore.ResponseCompression": "1.0.1
.-
Default Gzip Output Compression
Compress everything using the default Gzip compression.
Everything means the following MIME output
- text/plain
- text/css
- application/javascript
- text/html
- application/xml
- text/xml
- application/json
- text/json
-
-
Diagnostics(6)
These samples take a dependency of
"Microsoft.AspNetCore.Diagnostics":"1.1.1"
.-
Simply show a welcome page to indicate that the app is working properly. This sample does not use a startup class simply because it's just a one line code.
-
Show any unhandled exception in a nicely formatted page with error details. Only use this in development environment!
-
Use
IExceptionHandlerFeature
feature provided byMicrosoft.AspNetCore.Diagnostics.Abstractions
to create custom global exception page. -
Custom Global Exception Page - 2
Similar to the previous one except that that we use the custom error page defined in separate path.
-
Use
UseStatusCodePagesWithRedirects
. Beware: This extension method handles your 5xx return status code by redirecting it to a specific url. It will not handle your application exception in general (for this useUseExceptionHandler
- check previous samples). -
Here we go into the weeds of analysing middlewares in your request pipeline. This is a bit complicated. It requires the following packages:
Microsoft.AspNetCore.MiddlewareAnalysis
Microsoft.Extensions.DiagnosticAdapter
Microsoft.Extensions.Logging.Console
-
-
Static Files(6)
This additional dependency is required to enable the functionality
"Microsoft.AspNetCore.StaticFiles": "1.1.0"
.-
Simply serve static files (html, css, images, etc).
There are two static files being served in this project, index.html and hello.css. They are stored under
wwwroot
folder, which is the default folder location for this library.To access them you have to refer them directly e.g.
localhost:5000/index.html
andlocalhost:5000/hello.css
. -
Allow listing and browsing of your
wwwroot
folder. -
Combines the functionality of
UseStaticFiles, UseDefaultFiles, and UseDirectoryBrowser
. -
Customize the way Directory Browsing is displayed. In this sample the custom view only handles flat directory. We will deal with more complex scenario in the next sample.
-
Custom Directory Formatter - 2
Show custom Directory Browsing and handle directory listing as well as files.
-
Use Directory Browsing on a certain path using
DirectoryBrowserOptions.RequestPath
, e.g./browse
.
-
-
Web Sockets (5)
We are going to explore websocket functionality provided by ASP.NET Core. All the samples here require
Microsoft.AspNetCore.WebSockets
.Warning: These samples are low level websocket code. For production, use SignalR. Yes I will work on SignalR samples soon.
-
This is the simplest web socket code you can write. It simply returns what you sent. It does not handle the closing of the connection. It does not handle data that is larger than buffer. It only handles text payload.
-
We improve upon the previous sample by adding console logging (requiring
Microsoft.Extensions.Logging.Console
package) and handling data larger than the buffer. I set the buffer to be very small (4 bytes) so you can see how it works. -
We improve upon the previous sample by enabling broadcast. What you see here is a very crude chat functionality.
-
We improve upon the previous sample by handling closing event intiated by the web client.
-
Implement a rudimentary single channel chat server.
-
-
Server Side Events (1)
-
This server will send a 'hello world' greeting forever.
-
-
Syndications (2)
We are using the brand new
Microsoft.SyndicationFeed.ReaderWriter
package to read RSS and ATOM feeds.-
This is the shortest amount of code to read an RSS feed. This example read the feed from the inventor of RSS, Dave Winer at http://scripting.com/rss.xml.
-
Syndication - Read RSS with extensions
This sample process RSS Outline Extension.
-
-
Misc (3)
-
Serve markdown file as html file. You will see how you can create useful app using a few basic facilities in aspnetcore.
We take
"CommonMark.Net" : "0.13.4"
as dependency. -
Markdown server - implemented as middleware component
Serve markdown file as html file. It has the same exact functionality as Markdown server but implemented using middleware component.
We take
"CommonMark.Net" : "0.13.4"
as dependency.Check out the documentation on how to write your own middleware.
-
Give it a string and it will generate a secure hash for you, e.g.
localhost:5000?password=mypassword
.We add dependency
"Microsoft.AspNetCore.Identity": "1.1.0-*"
to enable this functionality.
-
-
Trimming (1)
This section shows the various way on how to trim the size of your application by using Microsoft.Packagin.Tools.Trimming
-
Trimming Microsoft.AspNetCore.All hello world application
Run
dotnet publish
ordotnet build
and read the output in your terminal. It will read something similar toTrimmed 128 out of 180 files for a savings of 20.8 MB Final app size is 3.2 MB
. You can turn off the trimming by setting<TrimUnusedDependencies>true</TrimUnusedDependencies>
tofalse
at the project file.
-
-
Modules (1)
This section shows how to create pluggable and extensible web system using
Orchardcore Modules
system.-
Run
dotnet watch run
at theweb
folder. This example shows a module that just writes "hello world".The
module1
project requiresOrchardCore.Module.Targets
and the hostweb
project requiresOrchardCore.Application.Targets
andOrchardCore.Modules
.
-
-
Middleware (1)
-
Use
Microsoft.AspNetCore.Buffering 0.2.2
middleware to implement response buffering facility. This will allow you to change your response after you write them.
-
-
Device Detection (1)
The samples in this section rely on Wangkanai.Detection library.
-
This is the most basic device detection. You will be able to detect whether the client is a desktop or a mobile client.
-
-
Owin (1)
All these samples require
Microsoft.AspNetCore.Owin
package. These are low level samples and in most cases are not relevant to your day to day ASP.NET Core development.-
Hello world the hard way.
-
-
SignalR (1)
SignalR is the real time communication library designed for ASP.NET Core. This library is still in
alpha 2
status at the moment. Check back this section often. We are going to be up to date with the latest SignalR revisions.-
This sample demonstrate on how to broadcast received input to all connected clients.
-
These are other aspnetcore resources with code samples