In the last post Introduction to OWN we discussed what is OWIN and looked at the OWIN specification. In this tutorial, we will build a small application and show you how to create OWIN Middleware.
Table of Contents
Create the Project
Create a new empty MVC application. Add the HomeController. Create an Index View and return “Hello world” from the View
If you are new to ASP.NET MVC then you can refer to the following tutorials
- Create ASP.NET MVC Application
- NET MVC Tutorial – Add View
- NET MVC Tutorial – Add Model
- NET MVC Tutorial – Add CRUD Operation
Adding OWIN References
OWIN is just a specification. KATANA the Implementation of OWIN specification. The following namespaces are from KATANA Project.
Microsoft.Owin
The Microsoft.Owin namespace has classes that support OWIN collections. This is basically a helper namespace. It has types and abstractions which help in creating OWIN Components. You can Install it from Nuget using the following command.
1 2 3 | Install-Package Microsoft.Owin |
Microsoft.owin.host.systemweb
This is OWIN Server, which runs on the IIS (Host). This package is the layer between the IIS and OWIN pipeline. This namespace contains the types related to handling OWIN requests. This module is responsible for starting the OWIN pipeline
1 2 3 | Install-Package Microsoft.Owin.Host.systemWeb |
Run the Application
Run and you will receive the following error
The following errors occurred while attempting to load the app.
– No assembly found containing an OwinStartupAttribute.
– No assembly found containing a Startup or [AssemblyName].Startup class.
To disable OWIN startup discovery, add the appSetting owin:AutomaticAppStartup with a value of “false” in your web.config.
To specify the OWIN startup Assembly, Class, or Method, add the appSetting owin:AppStartup with the fully qualified startup class or configuration method name in your web.config.
The above error says that the OWIN is unable to find the startup class.
Startup class
Startup class is similar to global.asax in classic ASP.NET. OWIN Applications look for this class during the application startup. Startup class is where middlewares are registered to be used in the application pipeline. There are a few different ways you can specify the location of the startup class.
Configuration file
The configuration file is the first place where OWIN looks for the startup class. This information is provided under the appSettings section as follows
1 2 3 4 5 | <appSettings> <add key="owin:appStartup" value="NameSpaceHere.StartupClassNameHere " /> </appSettings> |
OwinStartup Attribute
OwinStartup Attribute is added to the startup class. Here replace the NameSpaceHere.StartupClassNameHere with the actual root namespace and startup class.
1 2 3 | [assembly: OwinStartup(typeof(NameSpaceHere.StartupClassNameHeres))] |
Root namespace
Providing the startup class at the root namespace of the application with the method signature Configuration (IAppBuilder app)
The OWIN looks for startup class in the Configuration file. If not found, then looks for a class with OwinStartup Attribute. Finally, in the Root namespace with the name startup.
Add Startup Class
We can easily add an OWIN Startup class by selecting the Project right click and select OWIN Startup from the list of Options
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [assembly: OwinStartup(typeof(ASPNetOWIN.Startup))] namespace ASPNetOWIN { public class Startup { public void Configuration(IAppBuilder app) { } } } |
Our First OWIN Middleware
Now let us create our First Middleware. Create class under the root folder of your project and name it as MyFirstMiddleware.cls
OWIN specification requires two things from our middleware
- Every middleware that we write must have the following signature. A Func which accepts the Environmental dictionary and returns a task.
1 2 3 | Func<IDictionary<string, object>, Task> |
This is actually the reference to the next middleware on the list
- An Invoke method. This is by convention. OWIN uses reflection to find this method and executes it. It passes the Environmental dictionary to the invoke method
Add a new class and call it myFirstMiddleware
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | using System.Threading.Tasks; using Microsoft.Owin; public class MyFirstMiddleware { private readonly Func<IDictionary<string, object>, Task> _next; public MyFirstMiddleware(Func<IDictionary<string,object>,Task> next) { _next = next; } public async Task Invoke(IDictionary<string,object> enviroment) { // do something HttpContextBase context= (HttpContextBase) enviroment["System.Web.HttpContextBase"]; context.Response.Write("Hello from the First Middleware <br />"); await _next.Invoke(enviroment); context.Response.Write("Return from the First Middleware <br />"); } } |
In the above code our constructor accepts the Func<IDictionary<string,object>,Task>. We need to create a local variable to store this reference. This is done by the variable __next in the above code.
Invoke method accepts the Environmental dictionary (IDictionary<string,object>). Use this method to perform some task. Once finished call the next Middleware using _next.Invoke(enviroment) and wait for it.
Registering the OWIN Middleware
The configuration method of Startup class is automatically invoked by the OWIN Server. Inside the Configuration method middleware’s are registered using the use method of the IAppBuilder interface.
IAppBuilder is Interface is defined in the Owin namespace. It has Properties field which is of IDictionary<string, object>. It has a Use method which takes the middleware to be registered. All OWIN Middlewares are registered using the Use method. The Middlewares are processed in the order they are registered using the IAppBuilder.Use method
1 2 3 4 5 6 | public void Configuration(IAppBuilder app) { app.Use<MyFirstMiddleware>(); } |
Run the Application
The above screenshot is the output from the application. Put a breakpoint inside the Invoke method and check the values of the environment variables.
Our Second Middleware
There is another simpler way to create the Middleware. That is by Inheriting from the abstract Base class OwinMiddleware. This class is defined in the namespace Microsoft.Owin.
OwinMiddleware class provides the strongly typed layer around the AppFunc. It Also provides IOwinContext implementation to the Environmental dictionary which is passed to the invoke method. The code for the second middleware is as shown below
This is the preferred way of writing the OWIN middlewares
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class MySecondMiddleware :OwinMiddleware { public MySecondMiddleware(OwinMiddleware next): base(next) { } public override async Task Invoke(IOwinContext context) { // do something context.Response.Write("Hello from the Second Middleware <br />"); await Next.Invoke(context); context.Response.Write("Return from the second Middleware <br />"); } } |
Registering the Middleware
1 2 3 4 5 6 7 | public void Configuration(IAppBuilder app) { app.Use<MyFirstMiddleware>(); app.Use(typeof(MySecondMiddleware)); } |
Registering the Middleware is similar to the what we did for the FirstMidleware except we now pass the middleware using typeOf operator.
Our Third Middleware
You can register the middleware by creating the instance of the middleware. In such cases, the middleware must implement the Initialize method which accepts the Func<IDictionary<string,object>,Task>.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class MyThirdMiddleware { AppFunc _next; public void Initialize(AppFunc next) { _next = next; } public async Task Invoke(IDictionary<string, object> environment) { // do something HttpContextBase context = (HttpContextBase)environment["System.Web.HttpContextBase"]; context.Response.Write("Hello from the Third Middleware <br />"); await _next.Invoke(environment); context.Response.Write("Return from the Third Middleware <br />"); } } |
The only thing that changed in the above code is instead of passing Func<IDictionary<string,object>,Task> in the constructor we are using the Initialize method
Registering the OWIN Middleware
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class Startup { public void Configuration(IAppBuilder app) { app.Use<MyFirstMiddleware>(); app.Use(typeof(MySecondMiddleware)); MyThirdMiddleware third = new MyThirdMiddleware(); app.Use(third); } } |
Note that we have created the instance of the MyThirdMiddleware and used it to register the middleware
Conclusion
We have learned how to create and use OWIN Middleware in our Application. The new ASP.NET Identity system makes extensive use of OWIN Middleware. You can refer to these tutorials from the following links.
ASP.NET Identity Tutorial using OWIN
- Introduction to ASP.NET Identity
- NET Identity Tutorial – Basics
- NET Identity Tutorial -OWIN Setup
- NET Identity tutorial – User login and Registration
Microsoft.Owin is not compatible with .netcore3.1