Click here to Skip to main content
14,661,413 members
Articles » Web Development » ASP.NET » General
Article
Posted 8 Sep 2016

Tagged as

Stats

26.4K views
5 bookmarked

Implement Owin Pipeline using ASP.NET Core

Rate this:
3.00 (3 votes)
Please Sign up or sign in to vote.
3.00 (3 votes)
8 Sep 2016CPOL
How to implement OWIN pipeline using ASP.NET Core
ASP.NET Core is incredibly amazing to implement high-performance and powerful web applications. At this time, we should customize that to have all the great Microsoft's features. In this post, we will learn to implement OWIN pipeline.

Introduction

As you probably know, ASP.NET Core tooling such as Thinktecture IdentityServer, OData, SinglarR, etc. have not been implemented yet. Since the ASP.NET Core popularity is rising among the .NET programmers and lots of software start by this framework these days, the ability to use the above feature in ASP.NET Core increased in importance.

The most reasonable way to use OData... ASP Core is implementing Owin pipeline beside ASP Core pipeline, not as an alternative!

As will be told in the rest of the article, we use these two architectures together.

At the moment cause of packages like OData, SignalR,.. have not released in .NetCore version so we have to use full .NET Framework and of course, we can't have cross-platform application and use another OS like Linux to implement application but as soon as these packages are released in .NetCore framework version, we can lay away full .NET and only use .NetCore. Since the owin is just a standard, not an implemented framework, it does not have any problem in ASP.NET Core so we can use them together easily and we will have cross-platform application later without big refactoring in codes.

The practical of this example is "Nancy" that has released .NET Core version and we can use it on Owin pipeline and of course everything is cool, you can find code in this article by Scott Hanselman.

Prerequisite

The prerequisite of this article is familiar with ASP.NET Core, Middleware and Owin standard pipeline, plus you need Visual Studio 2015 update 3 to have ASP.NET Core.

Using the Code

So far, I found the target of this way is an ability to use tools that have compatibility to Owin and arrived in a stable version. For instance, identity server 4 is being prepared and has compatibility to ASP Core but it's a beta version and of course, is not stable and the main part is we don't have final release time exactly!

Create a C# project of ASP.NET Core web application fully using .NET Framework and name it "OwinCore".

Image 1

And in the next part, select a template of Empty.

Image 2

I will not explain more in ASP.NET Core and I assume that you are already familiar with this framework.

OK, now open "project.json" file to handle dependencies of this project.

Before I worry you to see lots of dependencies, I should say that the main important packages to use Owin are just "Microsoft.Owin" & "Microsoft.AspNetCore.Owin" and other packages are the just cause of show how this way is flexible and we can have different packages of different architectures together in a project.

"dependencies": {
    "Microsoft.AspNet.OData": "5.9.1",
    "Microsoft.AspNet.SignalR": "2.2.1",
    "Microsoft.AspNet.WebApi.Client": "5.2.3",
    "Microsoft.AspNet.WebApi.Core": "5.2.3",
    "Microsoft.AspNet.WebApi.Owin": "5.2.3",
    "Microsoft.AspNetCore.Diagnostics": "1.0.0",
    "Microsoft.AspNetCore.Hosting": "1.0.0",
    "Microsoft.AspNetCore.Mvc": "1.0.0",
    "Microsoft.AspNetCore.Owin": "1.0.0",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
    "Microsoft.Extensions.Logging.Console": "1.0.0",
    "Microsoft.Net.Http": "2.2.29",
    "Microsoft.Owin": "3.0.1",
    "Microsoft.Owin.Diagnostics": "3.0.1",
    "Microsoft.Owin.FileSystems": "3.0.1",
    "Microsoft.Owin.StaticFiles": "3.0.1",
    "Newtonsoft.Json": "9.0.1"
  },
//etc...

After saving this file, you can see Output window to see downloaded files from NuGet package manager, you see OData, SignalR, Owin and beside those, we have AspNetCore.Mvc. The reason for these two different types of packages are going to work together and don't have any problems.

In the main of your project, create a class named "OwinExtensions" with this content:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Owin.Builder;
using Microsoft.Owin.BuilderProperties;
using Owin;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace OwinCore
{
    public static class OwinExtensions
    {
        public static IApplicationBuilder UseOwinApp(
            this IApplicationBuilder aspNetCoreApp,
            Action<IAppBuilder> configuration)
        {
            return aspNetCoreApp.UseOwin(setup => setup(next =>
            {
                AppBuilder owinAppBuilder = new AppBuilder();

                IApplicationLifetime aspNetCoreLifetime = 
                        (IApplicationLifetime)aspNetCoreApp.ApplicationServices.GetService
                        (typeof(IApplicationLifetime));

                AppProperties owinAppProperties = new AppProperties(owinAppBuilder.Properties);

                owinAppProperties.OnAppDisposing = 
                       aspNetCoreLifetime?.ApplicationStopping ?? CancellationToken.None;

                owinAppProperties.DefaultApp = next;

                configuration(owinAppBuilder);

                return owinAppBuilder.Build<Func<IDictionary<string, object>, Task>>();
            }));
        }
    }
}

An extension method named "UseOwinApp" added to IApplicationBuilder regarding ASP.NET Core and inside that, create an instance of AppBuilder regarding Owin pipeline that causes Owin pipeline will work beside of ASP Core pipeline.

Now we want to create custom Owin middleware and register that in Startup of application. Create a class named "AddSampleHeaderToResponseHeadersOwinMiddleware" with this content:

using Microsoft.Owin;
using System.Threading.Tasks;

namespace OwinCore
{
    public class AddSampleHeaderToResponseHeadersOwinMiddleware : OwinMiddleware
    {
        public AddSampleHeaderToResponseHeadersOwinMiddleware(OwinMiddleware next)
            : base(next)
        {
        }
        public async override Task Invoke(IOwinContext context)
        {
            //throw new InvalidOperationException("ErrorTest");

            context.Response.Headers.Add("Test", new[] { context.Request.Uri.ToString() });

            await Next.Invoke(context);
        }
    }
}

It's a class inherited from OwinMiddleware and Invoke is an overridden method with IOwinContext and inside that, we can implement our custom middleware.

I commented Exception cause we need it later, and in the next line, in a response of header of each request, it creates an object named "Test" with Uri value.

And the next line says that you can go to the next middleware.

Now, open the "Startup.cs" and edit "Configure" method like this:

public void Configure(IApplicationBuilder aspNetCoreApp, IHostingEnvironment env)
        {
            aspNetCoreApp.UseOwinApp(owinApp =>
            {
                if (env.IsDevelopment())
                {
                    owinApp.UseErrorPage(new ErrorPageOptions()
                    {
                        ShowCookies = true,
                        ShowEnvironment = true,
                        ShowExceptionDetails = true,
                        ShowHeaders = true,
                        ShowQuery = true,
                        ShowSourceCode = true
                    });
                }

                owinApp.Use<AddSampleHeaderToResponseHeadersOwinMiddleware>();
            });
        }

By using UseOwinApp, we can register owin middleware. What is remarkable is we have used owin middleware beside of IHostingEnviroment related on ASP NET Core pipeline. owinApp.UseErrorPage has taken of Microsoft.Owin.Diagnostics, and in the next line, we have registered our custom owin middleware.

Run the project and you should see this in the response of your header of any request:

Image 3

Now, if we have uncommented that Exception in custom middleware and run again, you should see this page in the development environment.

Image 4

Then comment that exception and continue on...

Because of showing that Owin and ASP.NET Core pipeline can work beside together easily, we create a new custom ASP.NET Core middleware and register that on "Configure" method.

Create a new class named "AddSampleHeaderToResponseHeadersAspNetCoreMiddlware" with this content:

namespace OwinCore
{
    public class AddSampleHeaderToResponseHeadersAspNetCoreMiddlware
    {
        private readonly RequestDelegate Next;

        public AddSampleHeaderToResponseHeadersAspNetCoreMiddlware(RequestDelegate next)
        {
            Next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            //throw new InvalidOperationException("ErrorTest");

            context.Response.Headers.Add("Test2", new[] { "some text" });

            await Next.Invoke(context);
        }
    }
}

And in Configure method on Startup class, we have this changeset:

public void Configure(IApplicationBuilder aspNetCoreApp, IHostingEnvironment env)
        {
            aspNetCoreApp.UseOwinApp(owinApp =>
            {
                if (env.IsDevelopment())
                {
                    owinApp.UseErrorPage(new ErrorPageOptions()
                    {
                        ShowCookies = true,
                        ShowEnvironment = true,
                        ShowExceptionDetails = true,
                        ShowHeaders = true,
                        ShowQuery = true,
                        ShowSourceCode = true
                    });
                }

                owinApp.Use<AddSampleHeaderToResponseHeadersOwinMiddleware>();
            });

            aspNetCoreApp.UseMiddleware<AddSampleHeaderToResponseHeadersAspNetCoreMiddlware>();
        }

Now "AddSampleHeaderToResponseHeadersAspNetCoreMiddlware" middleware has been registered and you can see the result on response of header of any request.

After running the project, you should see something like this:

Image 5

You see our middleware of different pipelines are working together and because Owin middleware has registered before ASP.NET Core middleware, they will be executed in the sequence of registered middleware.

"Test" has created by owin and "Test2" has created by ASP.NET Core.

Now I want to implement OData protocol using owin pipeline in ASP NET Core application.

First, create a class named "Product" like this:

namespace OwinCore
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
}

And now, we create a class named "ProductsController" with this content:

namespace OwinCore
{
    public class ProductsController : ODataController
    {
        [EnableQuery]
        public IQueryable<Product> Get()
        {
            return new List<Product>
            {
                 new Product { Id = 1, Name = "Test" , Price = 10 }
            }
            .AsQueryable();
        }
    }
}

If you are familiar with OData protocol, you would know how this controller works but if not, it's a simple OData controller using web API and Get function returns an IQueryable of Product and we can have filter on requested query using third party tools such as JayData or Breeze.

And it's clear that OData is nuget related to entity framework!

OData config is incredibly easy and you can do that in Configure method in this way:

public void Configure(IApplicationBuilder aspNetCoreApp, IHostingEnvironment env)
        {
            //aspNetCoreApp.UseMvc();

            aspNetCoreApp.UseOwinApp(owinApp =>
            {
                if (env.IsDevelopment())
                {
                    owinApp.UseErrorPage(new ErrorPageOptions()
                    {
                        ShowCookies = true,
                        ShowEnvironment = true,
                        ShowExceptionDetails = true,
                        ShowHeaders = true,
                        ShowQuery = true,
                        ShowSourceCode = true
                    });
                }
                // owinApp.UseFileServer(); as like as asp.net core file server middleware
                // owinApp.UseStaticFiles(); as like as asp.net core static files middleware
                // owinApp.UseWebApi(); asp.net web api / odata / web hooks


                //OData config
                HttpConfiguration webApiConfig = new HttpConfiguration();
                ODataModelBuilder odataMetadataBuilder = new ODataConventionModelBuilder();
                odataMetadataBuilder.EntitySet<Product>("Products");
                webApiConfig.MapODataServiceRoute(
                    routeName: "ODataRoute",
                    routePrefix: "odata",
                    model: odataMetadataBuilder.GetEdmModel());
                owinApp.UseWebApi(webApiConfig);
                //End of OData config

                owinApp.MapSignalR();

                //owinApp.Use<AddSampleHeaderToResponseHeadersOwinMiddleware>();
            });

            //aspNetCoreApp.UseMiddleware<AddSampleHeaderToResponseHeadersAspNetCoreMiddlware>();

OData needs an instance of HttpConfiguration, using ODataModelBuilder we can add all needed EntitySet and using MapODataServiceRoute we can handle routing and if we have multiple OData endpoints, we can have multiple routing easily with different routeName and routePrefix.

By using implementation of owin pipeline, we could config OData easily such normal ASP.NET project and you can see you can config SignalR and other packages too.

Run the project and send this get request:

http://localhost:YourPort/odata/Product

The response of this request should be something like the below object:

{
 "@odata.context":"http://localhost:4675/odata/$metadata#Products","value":[
    {
      "Id":1,"Name":"Test","Price":10
    }
  ]
}

Lots of owin middlewares such as "Thinktecture IdentityServer", "NWebSec", "Facebook OAuth",... can implement by this tutorial on ASP NET Core applications by their owin configuration easily.

After preparing these packages in .NET Core edition, we can use that easily without big code refactoring!

Conclusion

ASP.NET Core is incredibly amazing to implement high-performance and powerful web applications. At this time, we should customize that to have all the great Microsoft's features.

If you have any problems, you can easily follow instruction on Github and have rich commit comments to understand this article, you can find an implementation of Autofac as an IOC container and SignalR too, I'll create an article to describe those features soon.

History

  • 8th September, 2016: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ali_Khalili
Software Developer (Senior)
Iran (Islamic Republic of) Iran (Islamic Republic of)
I'm Ali Khalili
senior consultant - software developer/architect
love anything modern such as .Net core - typescript (& es6 - angularjs - reactjs)
and other cool Microsoft technologies

Comments and Discussions

 
-- There are no messages in this forum --