Sorted By: Tag (katana)

Challenge of Solving an ASP.NET Web API Self-Hosting Problem: No HTTP resource was found that matches the request URI

Couple of weeks ago, one of my former coworkers ran across a very weird problem when he was prototyping on some of his ideas with ASP.NET Web API: No HTTP resource was found that matches the request URI. Let's see what this issue was all about and what is the solution.
2014-04-16 08:28
Tugberk Ugurlu


Couple of weeks ago, one of my former coworkers ran across a very weird problem when he was prototyping on some of his ideas with ASP.NET Web API. He was hosting his ASP.NET Web API application on a console application using the Microsoft.Owin.Hosting components and Microsoft.Owin.Host.HttpListener host. His solution structure was also very simple. He put all of his controllers, message handlers, filters, etc. in one class library and all the hosting logic inside the console application. The below structure was pretty similar to what he did:

Screenshot 2014-04-16 10.36.01

Console application also has very little amount of code:

class Program
{
    static void Main(string[] args)
    {
        using (WebApp.Start("http://localhost:5555/", Start))
        {
            Console.WriteLine("Started listening on localhost:5555");
            Console.ReadLine();
            Console.WriteLine("Shutting down...");
        }
    }

    static void Start(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();
        config.Routes.MapHttpRoute("DefaultHttpRoute", "api/{controller}");
        app.UseWebApi(config);
    }
}

As you can see, it's all done by the book. However, he was constantly getting 404 when he fired up the application and sent a request to /api/cars:

Screenshot 2014-04-16 10.41.50

"No HTTP resource was found that matches the request URI". It's pretty strange. After I looked into the issue for a while, I was able to figure what the problem is:

Screenshot 2014-04-16 10.45.50

Let's make this a little bit interesting and have a look at the modules loaded into the AppDomain :)

Screenshot 2014-04-16 10.49.30

Notice that the WebApiStrangeConsoleHostSample.dll was never loaded into the AppDomain because we never used it even if it's referenced. As ASP.NET Web API uses reflection to determine the controller and the action, it never finds the CarsController. To prove our point here, I'll load the assembly manually:

static void Main(string[] args)
{
    Assembly.LoadFrom(Path.Combine(Environment.CurrentDirectory, "WebApiStrangeConsoleHostSample.dll"));
    using (WebApp.Start("http://localhost:5555/", Start))
    {
        Console.WriteLine("Started listening on localhost:5555");
        Console.ReadLine();
        Console.WriteLine("Shutting down...");
    }
}

The result is a success:

Screenshot 2014-04-16 10.56.56

However, this is not an ideal solution and I bet that you never run into this issue before. Why? Because, you wise developer keep your hosting agnostic bootstrap code inside the same assembly with you core ASP.NET Web API layer and you call this inside the host application. As soon as you call a method from the core layer assembly, that assembly will be loaded into your AppDomain.

public static class WebApiConfig
{
    public static void Configure(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute("DefaultHttpRoute", "api/{controller}");
    }
}
class Program
{
    static void Main(string[] args)
    {
        using (WebApp.Start("http://localhost:5555/", Start))
        {
            Console.WriteLine("Started listening on localhost:5555");
            Console.ReadLine();
            Console.WriteLine("Shutting down...");
        }
    }

    static void Start(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();
        WebApiConfig.Configure(config);
        app.UseWebApi(config);
    }
}

There is one other potential solution to a problem which is similar to this one. That is to replace the IAssembliesResolver service as Filip did in this post.

Simple OAuth Server: Implementing a Simple OAuth Server with Katana OAuth Authorization Server Components (Part 1)

In my previous post, I emphasized a few important facts on my journey of building an OAuth authorization server. As great people say: "Talk is cheap. Show me the code." It is exactly what I'm trying to do in this blog post. Also, this post is the first one in the "Simple OAuth Server" series.
2014-04-01 14:30
Tugberk Ugurlu


In my previous post, I emphasized a few important facts on my journey of building an OAuth authorization server. As great people say: "Talk is cheap. Show me the code." It is exactly what I'm trying to do in this blog post. Also, this post is the first one in the "Simple OAuth Server" series.

What are We Trying to Solve Here?

What we want to achieve at the end of the next two blog posts is actually very doable. We want to have a console application where we handle calls to our protected web service endpoints and access them in a delegated manner which means that the client will actually access the resources on behalf of a user (in other words, resource owner). However, we won't be accessing the web service with resource owner's credentials (username and password). Instead, we will use the credentials to obtain an access token through the resource owner credentials grant and use that token to access the resources from that point on. After this blog post, we will expend our needs and build on top of our existing solution with the upcoming posts. That's why this post will be a little bit detailed about how you could set up the project and we will only cover building the OAuth server part.

Building the Application Infrastructure

I'll start by creating the ASP.NET Web API application. As mentioned, our application will evolve over time with the upcoming posts. So, this post will only cover the minimum requirements. So, bare this in mind just in case. I used the provided project templates in Visual Studio 2013 to create the project. For this blog post content, we only need ASP.NET Web API components to create our project.

Screenshot 2014-03-31 11.19.58 

Screenshot 2014-03-31 11.22.19

At the time of writing this post, visual Studio 2013 had the old ASP.NET Web API bits and it's worth updating the package before we continue:

Screenshot 2014-03-31 11.26.09

The OAuth authorization server and the ASP.NET Web API endpoints will be hosted inside the same host in our application here. In your production application, you would probably don't want to do this but for our demo purposes, this will be simpler.

Now we are ready to build on top of the project template. First thing we need is a membership storage system. Nothing would be better than new ASP.NET Identity components. I will use the official Entity Framework port of the ASP.NET Identity for our application here. However, you are free to choose your own data storage engine. Scott Allen has a great blog post about the extensibility of ASP.NET Identity and he listed available open source projects which provide additional storage options for ASP.NET Identity such as AspNet.Identity.RavenDB.

Screenshot 2014-03-31 11.36.12

There are two more packages that you need to install. One of them is Microsoft.AspNet.Identity.Owin. This package provides several useful extensions you will use while working with ASP.NET Identity on top of OWIN. The other one is Microsoft.Owin.Host.SystemWeb package which enables OWIN-based applications to run on IIS using the ASP.NET request pipeline.

The packages we just installed (Microsoft.AspNet.Identity.Owin) also brought down some other packages as its dependencies. One of those dependency packages is Microsoft.Owin.Security.OAuth and this is the core package that includes the components to support any standard OAuth 2.0 authentication workflow. Just wanted to highlight this fact as this is an important part of the project.

I will create the Entity Framework DbContext which will hold membership and OAuth client data. ASP.NET Identity Entity Framework package already has the DbContext implementation for the membership storage and our context class will be derived from that.

public class OAuthDbContext : IdentityDbContext
{
    public OAuthDbContext()
        : base("OAuthDbContext")
    {
    }

    public DbSet<Client> Clients { get; set; }
}

OAuthDbContext class is derived from IdentityDbContext class as you see. Also notice that we have another DbSet property for clients. That will represent the information of the clients. The Client class is a shown below:

public class Client
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string ClientSecretHash { get; set; }
    public OAuthGrant AllowedGrant { get; set; }

    public DateTimeOffset CreatedOn { get; set; }
}

This is the minimum that we need from the client to register in our authorization server. For certain grants, the client doesn't need to have a secret but for "Resource Owner Password Credentials Grant", it's mandatory. The client is also allowed for only one grant, that's all. This is not inside the OAuth 2.0 specification but it's the recommended approach. OAuthGrant is an enum and has the following values:

public enum OAuthGrant
{
    Code = 1,
    Implicit = 2,
    ResourceOwner = 3,
    Client = 4
}

These are all we need for now and we are ready to create the database. I will use Entity Framework Migrations feature to stand up the database and seed some data for demo purposes. As a one time process, I need to enable migrations first by running the "Enable-Migrations" command from the Package Manager Console.

Screenshot 2014-03-31 14.39.34

I will run the another command to add a migration code to reflect my context to a database schema: Add-Migration:

Screenshot 2014-03-31 14.41.44

Enable-Migration command created an internal class called Configuration and it contains a Seed method. I can use that seed method to inject some data during the database creation process:

protected override void Seed(SimpleOAuthSample.Models.OAuthDbContext context)
{
    context.Clients.AddOrUpdate(
        client => client.Name,
        new Client
        {
            Id = "42ff5dad3c274c97a3a7c3d44b67bb42",
            Name = "Demo Resource Owner Password Credentials Grant Client",
            ClientSecretHash = new PasswordHasher().HashPassword("client123456"),
            AllowedGrant = OAuthGrant.ResourceOwner,
            CreatedOn = DateTimeOffset.UtcNow
        });

    context.Users.AddOrUpdate(
        user => user.UserName,
        new IdentityUser("Tugberk")
        {
            Id = Guid.NewGuid().ToString("N"),
            PasswordHash = new PasswordHasher().HashPassword("user123456"),
            SecurityStamp = Guid.NewGuid().ToString(),
            Email = "tugberk@example.com",
            EmailConfirmed = true
        });
}

Now, I will use the Update-Database command to create my database:

Screenshot 2014-03-31 17.04.38

This command just created the database with the seed data on my SQL Express:

image

We will interact with our database mostly through the UserManager class which ASP.NET Identity core library provides. However, we will still use the OAuthDbContext directly. To use those classes efficiently, we need to write some setup code. I'll do this inside the OWIN Startup class:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.CreatePerOwinContext<OAuthDbContext>(() => new OAuthDbContext());
        app.CreatePerOwinContext<UserManager<IdentityUser>>(CreateManager);
    }

    private static UserManager<IdentityUser> CreateManager(
        IdentityFactoryOptions<UserManager<IdentityUser>> options,
        IOwinContext context)
    {
        var userStore =
            new UserStore<IdentityUser>(context.Get<OAuthDbContext>());

        var manager =
            new UserManager<IdentityUser>(userStore);

        return manager;
    }
}

This is the minimum code that we can write to use the UserManager class inside our OWIN components efficiently. Although I'm not fan of this approach, I chose to do it this way since doing it in my way would complicate the post.

OAuth Authorization Server Application with Katana OAuthAuthorizationServerMiddleware

Here we come to the real meat of the post. I will now set up the OAuth 2.0 token endpoint to support Resource Owner Password Credentials Grant by using the OAuthAuthorizationServerMiddleware which comes with the Microsoft.Owin.Security.OAuth library. There is a shorthand extension method on IAppBuilder to use this middleware: UseOAuthAuthorizationServer. I will use this extension method to configure my OAuth 2.0 endpoints through the Configuration method of my Startup class:

public void Configuration(IAppBuilder app)
{
    //... 
	
    app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
    {
        TokenEndpointPath = new PathString("/oauth/token"),
        Provider = new MyOAuthAuthorizationServerProvider(),
        AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
#if DEBUG
        AllowInsecureHttp = true,
#endif
    });
}

I'm passing an instance of OAuthAuthorizationServerOptions here and setting a few of its properties. Everything is pretty much self explanatory except of Provider property. I'm setting an implementation of IOAuthAuthorizationServerProvider to Provider property to handle the request at the specific places. Fortunately, I didn't have to implement this interface from top to bottom as there is a default implementation of it (OAuthAuthorizationServerProvider) and I just needed to override the methods that I needed.

Spare some time to read the documentation of the OAuthAuthorizationServerProvider's methods. Those are pretty detailed and should give you a great head start.

public class MyOAuthAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    public override async Task ValidateClientAuthentication(
        OAuthValidateClientAuthenticationContext context)
    {
        string clientId;
        string clientSecret;

        if (context.TryGetBasicCredentials(out clientId, out clientSecret))
        {
            UserManager<IdentityUser> userManager = 
                context.OwinContext.GetUserManager<UserManager<IdentityUser>>();
            OAuthDbContext dbContext = 
                context.OwinContext.Get<OAuthDbContext>();

            try
            {
                Client client = await dbContext
                    .Clients
                    .FirstOrDefaultAsync(clientEntity => clientEntity.Id == clientId);

                if (client != null &&
                    userManager.PasswordHasher.VerifyHashedPassword(
                        client.ClientSecretHash, clientSecret) == PasswordVerificationResult.Success)
                {
                    // Client has been verified.
                    context.OwinContext.Set<Client>("oauth:client", client);
                    context.Validated(clientId);
                }
                else
                {
                    // Client could not be validated.
                    context.SetError("invalid_client", "Client credentials are invalid.");
                    context.Rejected();
                }
            }
            catch
            {
                // Could not get the client through the IClientManager implementation.
                context.SetError("server_error");
                context.Rejected();
            }
        }
        else
        {
            // The client credentials could not be retrieved.
            context.SetError(
                "invalid_client", 
                "Client credentials could not be retrieved through the Authorization header.");

            context.Rejected();
        }
    }

    public override async Task GrantResourceOwnerCredentials(
        OAuthGrantResourceOwnerCredentialsContext context)
    {
        Client client = context.OwinContext.Get<Client>("oauth:client");
        if (client.AllowedGrant == OAuthGrant.ResourceOwner)
        {
            // Client flow matches the requested flow. Continue...
            UserManager<IdentityUser> userManager = 
                context.OwinContext.GetUserManager<UserManager<IdentityUser>>();

            IdentityUser user;
            try
            {
                user = await userManager.FindAsync(context.UserName, context.Password);
            }
            catch
            {
                // Could not retrieve the user.
                context.SetError("server_error");
                context.Rejected();

                // Return here so that we don't process further. Not ideal but needed to be done here.
                return;
            }

            if (user != null)
            {
                try
                {
                    // User is found. Signal this by calling context.Validated
                    ClaimsIdentity identity = await userManager.CreateIdentityAsync(
                        user, 
                        DefaultAuthenticationTypes.ExternalBearer);

                    context.Validated(identity);
                }
                catch
                {
                    // The ClaimsIdentity could not be created by the UserManager.
                    context.SetError("server_error");
                    context.Rejected();
                }
            }
            else
            {
                // The resource owner credentials are invalid or resource owner does not exist.
                context.SetError(
                    "access_denied", 
                    "The resource owner credentials are invalid or resource owner does not exist.");

                context.Rejected();
            }
        }
        else
        {
            // Client is not allowed for the 'Resource Owner Password Credentials Grant'.
            context.SetError(
                "invalid_grant", 
                "Client is not allowed for the 'Resource Owner Password Credentials Grant'");

            context.Rejected();
        }
    }
}

Petty much all the methods you will implement, you will be given a context class and you can signal the validity of the request at any point by calling the Validated and Rejected method with their provided signatures. I implemented two methods above (ValidateClientAuthentication and GrantResourceOwnerCredentials) and I performed Validated and Rejected at several points as I have seen it fit.

An HTTP POST request made to "/oauth/token" endpoint with response_type parameter set to "password" will first arrive at the ValidateClientAuthentication method. This is the place where you should retrieve the client credentials and validate it. According to OAuth 2.0 specification, the client credentials can also be sent as request parameters. However, I don't think this is such a good idea comparing to sending the credentials through basic authentication. That's why I only tried to get it from the "Authorization" header. If the client credentials are valid, the request will continue. If not, it will not process further and the error response will be returned as described inside the OAuth 2.0 specification.

If the client credentials are valid and the "response_type" parameter is set to password, the request will arrive at the GrantResourceOwnerCredentials method. Inside this method there are three things we will essentials do:

  • Validate the client's allowed grant. I's check if it's set to ResourceOwner.
  • If the client's grant type is valid, validate the resource owner credentials.
  • If resource owner credentials are valid, generate a claims identity for the resource owner and pass it to the Validated method.

If all goes as expected, the middleware will issue the access token.

Calling the OAuth Token Endpoint and Getting the Access Token

Let's try out the pieces that we have built. As you see previously, I have seeded a sample client and a sample user when during the database creation process. I will use those information to generate a valid OAuth 2.0 "Resource Owner Password Credentials Grant" request.

Request:

POST http://localhost:53523/oauth/token HTTP/1.1
User-Agent: Fiddler
Content-Type: application/x-www-form-urlencoded
Authorization: Basic NDJmZjVkYWQzYzI3NGM5N2EzYTdjM2Q0NGI2N2JiNDI6Y2xpZW50MTIzNDU2
Host: localhost:53523
Content-Length: 56

grant_type=password&username=Tugberk&password=user123456

Response:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 550
Content-Type: application/json;charset=UTF-8
Expires: -1
Server: Microsoft-IIS/8.0
X-SourceFiles: =?UTF-8?B?RDpcRHJvcGJveFxBcHBzXFNhbXBsZXNcQXNwTmV0SWRlbnRpdHlTYW1wbGVzXFNpbXBsZU9BdXRoU2FtcGxlXFNpbXBsZU9BdXRoU2FtcGxlXG9hdXRoXHRva2Vu?=
X-Powered-By: ASP.NET
Date: Tue, 01 Apr 2014 13:56:32 GMT

{"access_token":"ydbP24rMOATt7TK3dBCjluD2F5LcLkoX8ud39X135x0a1LEvOgsPf0ekm4Lyu2a06Rv_Z105GRZT_NoclgTTf7Slt5_WNfe68zOUq22j6MqW4Fh__Abzjm6I8otDzxvCJpt5d73R-Um6GwTui3LDbcOk5bH2BZuQLTJsNLknbLPu_FdpgkYfBodUoyPiFhv5-gNBEsfp4gCZYfdKtlhaK0wtloZiIzH1_sNPhBt9FavSfThM5BeoWkz8PFxkv_cOsOhOIzK66nSx7B2XL7K9aLqPSJLxus2ud8GBZyteSeFi26L9oX9do7MyCL1nXa8D9DRWfcIXiQi1v19AwyhoupP3L-k89xOK6_NTSzYOVhSMG9Juz8VYHWGkJeYTmekmnVkCvQe7KMQ6PceeUFJnA88TkiHNhai0hV8j012OUxPpUN5zRPJOU81XywSkQ7oKE0UsX3hQamgFrXV9eA-TSwZd4Qr-P9w6a82OM66Te9E","token_type":"bearer","expires_in":1799}

We successfully retrieved the response and it contains the JSON response body which includes the access token in the format described inside the OAuth 2.0 specification.

Summary and What is Next

In this post, we have set up our authorization server and we have a working OAuth 2.0 token endpoint which only supports "Resource Owner Password Credentials Grant" for now. The code is available on GitHub if you are interested in. In the next post, we will create our web service and protect it using our authorization server. We will also see how we can call this web service successfully from a typical .NET application.

Resources

Short Introduction Video for OWIN and Project Katana

I've recorded a short video which covers the brief introduction of OWIN and Project Katana. That short video will give you an idea about OWIN and Project Katana.
2013-10-21 13:29
Tugberk Ugurlu


I've recorded a short video which covers the brief introduction of OWIN and Project Katana. That short video will give you an idea about OWIN and Project Katana and why we should care about it.

An Introduction to OWIN and Project Katana from Tugberk Ugurlu on Vimeo.

Let me know whether this recording is any help to you. Your feedback is always more than welcome. Enjoy!

Replace the Default Server of OwinHost.exe with Nowin in Visual Studio 2013

This post will show you how to you can replace the default server of OwinHost.exe with Nowin in Visual Studio 2013
2013-09-27 11:14
Tugberk Ugurlu


Wow, I cannot believe I'm writing this post :) It's really exciting to see that .NET web stack has evolved this much. First, we had a web framework shipping out of band: ASP.NET MVC. Then, we were given a chance to play with hosting agnostic web frameworks such as ASP.NET Web API and ASP.NET SignalR (I know, their names are still confusing and give an impression that those frameworks are still bound to ASP.NET but they are actually not). Recently, we have been embracing the idea of separating the application, server and the host from each other by making our applications OWIN compliant.

By this way, we can easily build our pipeline on our own and switch the underlying host or server easily. Visual Studio 2013 even has a really nice extensibility point to switch the underlying host and still have the F5 experience. OwinHost.exe is one of those hosts that we can use as an alternative to IIS. Today, we can even take this further and completely replace the underlying server (which is HttpListener by default with OwinHost.exe) by preserving the host. There is an OWIN compliant server implementation called Nowin developed by a very clever guy, Boris Letocha. This server uses a raw .NET socket to listen to the HTTP requests coming in through the wire and will respond to them. By looking at the repository's readme file, I can say that this component is not production ready but will work out just fine for demonstration purposes.

I created a mini sample application to show you this cool feature. You can find it on my GitHub OwinSamples repository, too. It only contains the following startup class and initially have two NuGet packages installed: Owin and OwinHost.

using AppFunc = Func<IDictionary<string, object>, Task>;

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Use(new Func<AppFunc, AppFunc>(ignoreNext => Invoke));
    }

    public async Task Invoke(IDictionary<string, object> env)
    {
        // retrieve the Request Data from the environment
        string path = env["owin.RequestPath"] as string;

        if (path.Equals("/", StringComparison.OrdinalIgnoreCase))
        {
            // Prepare the message
            const string Message = "Hello World!";
            byte[] bytes = Encoding.UTF8.GetBytes(Message);

            // retrieve the Response Data from the environment
            Stream responseBody = env["owin.ResponseBody"] as Stream;
            IDictionary<string, string[]> responseHeaders = 
                env["owin.ResponseHeaders"] as IDictionary<string, string[]>;

            // write the headers, response body
            responseHeaders["Content-Type"] = new[] { "text/plain" };
            await responseBody.WriteAsync(bytes, 0, bytes.Length);
        }
    }
}

I am not sure if you have noticed this but Visual Studio 2013 even has an item template for creating an OWIN startup class:

image

This seems nice but it secretly installs the Microsoft.Owin package, which is unnecessary if you ask me. Owin NuGet package should be enough IMHO.

I also applied the steps explained in my "OwinHost.exe on Visual Studio 2013" post to get my application running on top of OwinHost and here is the result:

image

Here, my host is OwinHost.exe and it uses the Microsoft.Owin.Host.HttpListener as the server by default. At the application level, we don't need to know or care about which server we are on but most of the OWIN server implementations expose their names through the server.Capabilities dictionary:

image

What we want to accomplish here is to keep the host as it is and only replace the server component that it uses underneath. As our host (OwinHost.exe) is OWIN compliant, it can work with any other type of OWIN compliant server implementations and one of them is Nowin. Installing Nowin over NuGet into your project is the first step that you need to do.

image

However, this's not enough by itself as OwinHost.exe has no idea that we want to use Nowin as our server. Luckily, we can manipulate the arguments we pass onto OwinHost.exe. You can configure these arguments through the Web pane inside the Visual Studio Project Properties window. Besides that, OwinHost.exe accepts a few command line switches and one of them is the –s (or –-server) switch to load the specified server factory type or assembly. These are all we needed.

image

After saving the changes we have made, we can run the application and get the same result on top of a completely different server implementation:

image

Also with the same way as we did earlier, we can see that the switch has been made and Nowin is in use:

image

Being able to do all of this is a very big deal; especially if you think that we have been tied to IIS for very long time. I'm so happy to see .NET web stack moving towards this flexible direction.

Logging in the OWIN World with Microsoft.Owin: Introduction

Microsoft implementation of OWIN (Microsoft.Owin or Katana for now) has a great logging infrastructure and this post will walk you through the basics of this component.
2013-09-18 16:14
Tugberk Ugurlu


Microsoft implementation of OWIN (called Microsoft.Owin or Katana for now) has a great infrastructure for logging under Microsoft.Owin.Logging namespace inside the Microsoft.Owin assembly. Same as all other Microsoft.Owin components, the logging infrastructure is built on top of interfaces and there are two of them: ILoggerFactory and ILogger. The default implementation is using .NET Framework tracing components heavily such as System.Diagnostics.TraceSource and System.Diagnostics.TraceSwitch. You can learn about these components and how to instrument your applications with them through the .NET Development Guide's Tracing section on MSDN.

The responsibility of the logger factory is to construct a new logger when needed. You can see how ILoggerFactory interface looks like below:

namespace Microsoft.Owin.Logging
{
    /// <summary>
    /// Used to create logger instances of the given name.
    /// </summary>
    public interface ILoggerFactory
    {
        /// <summary>
        /// Creates a new ILogger instance of the given name.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        ILogger Create(string name);
    }
}

As you can see, the Create method returns an ILogger implementation. The ILogger implementation is solely responsible for writing the logs through its one and only method: WriteCore.

namespace Microsoft.Owin.Logging
{
    /// <summary>
    /// A generic interface for logging.
    /// </summary>
    public interface ILogger
    {
        /// <summary>
        /// Aggregates most logging patterns to a single method.  This must be compatible with the Func representation in the OWIN environment.
        /// 
        /// To check IsEnabled call WriteCore with only TraceEventType and check the return value, no event will be written.
        /// </summary>
        /// <param name="eventType"></param>
        /// <param name="eventId"></param>
        /// <param name="state"></param>
        /// <param name="exception"></param>
        /// <param name="formatter"></param>
        /// <returns></returns>
        bool WriteCore(TraceEventType eventType, int eventId, object state, 
            Exception exception, Func<object, Exception, string> formatter);
    }
}

For these interfaces, there are two implementations provided by the Microsoft.Owin assembly for logging: DiagnosticsLoggerFactory (publicly exposed) and DiagnosticsLogger (internally exposed). However, these are the types provided by the Microsoft's OWIN implementation and don't belong to core .NET framework. As it's discouraged to put non-framework types inside the IAppBuilder properties dictionary and request's environment, a Func is put inside the IAppBuilder properties dictionary with a key named "server.LoggerFactory". Here is the signature of that Func.

using TraceFactoryDelegate = 
    Func
    <
        string, 
        Func
        <
            TraceEventType, 
            int, 
            object, 
            Exception, 
            Func
            <
                object, 
                Exception, 
                string
            >, 
            bool
        >
    >;

Through this delegate, you are expected to create a Func object based on the logger name and this Func will be used to write logs. The currently provided extension methods to work with the Katana’s logging infrastructure hides these delegates from you. Here are a few extension methods under Microsoft.Owin.Logging namespace for the IAppBuilder interface:

public static void SetLoggerFactory(
    this IAppBuilder app, ILoggerFactory loggerFactory);
    
public static ILoggerFactory GetLoggerFactory(
    this IAppBuilder app);
    
public static ILogger CreateLogger(
    this IAppBuilder app, string name);

All these extension methods work on the TraceFactoryDelegate Func instance shown above but it’s all hidden from us as mentioned.

So, how we can take advantage of this provided components? It’s quite easy actually. You can create separate loggers for each of your components using one of the CreateLogger extension method overloads for the IAppBuilder interface and use that logger to write log messages. The following is just a little sample to give you a hint:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        Log1(app);
        app.Use<MyCustomMiddleware>(app);
    }

    private void Log1(IAppBuilder app) 
    {
        ILogger logger = app.CreateLogger<Startup>();
        logger.WriteError("App is starting up");
        logger.WriteCritical("App is starting up");
        logger.WriteWarning("App is starting up");
        logger.WriteVerbose("App is starting up");
        logger.WriteInformation("App is starting up");

        int foo = 1;
        int bar = 0;

        try
        {
            int fb = foo / bar;
        }
        catch (Exception ex)
        {
            logger.WriteError("Error on calculation", ex);
        }
    }
}

public class MyCustomMiddleware : OwinMiddleware
{
    private readonly ILogger _logger;

    public MyCustomMiddleware(
        OwinMiddleware next, IAppBuilder app) : base(next)
    {
        _logger = app.CreateLogger<MyCustomMiddleware>();
    }

    public override Task Invoke(IOwinContext context)
    {
        _logger.WriteVerbose(
            string.Format("{0} {1}: {2}", 
            context.Request.Scheme, 
            context.Request.Method, 
            context.Request.Path));

        context.Response.Headers.Add(
            "Content-Type", new[] { "text/plain" });
            
        return context.Response.WriteAsync(
            "Logging sample is runnig!");
    }
}

There are a few things I would like to touch on here:

  • I used generic CreateLogger method to create loggers. This will create loggers based on the name of the type I’m passing in. In view of the default logger implementation provided by the Katana, this means that we will create TraceSource instances named as the full type name.
  • You can see that I receive an IAppBuilder implementation instance through the constructor of my middleware and I used that instance to create a logger specific to my middleware. I can hold onto that logger throughout the AppDomain lifetime as all members of my logger are thread safe.
  • Instead of using the WriteCore method to write logs, I used several extension methods such as WriteVerbose to write specific logs.

This is not enough by default as we didn’t configure what kind of tracing data we are interested in and how we would like to output them. We need to configure Trace Switches and Trace Listeners properly to instrument our application. Microsoft.Owin is root switch and if we enable it, we will see all messages we write through our loggers. The following configuration will enable the Microsoft.Owin switch:

<configuration>
  <system.diagnostics>
    <switches>
      <add name="Microsoft.Owin" value="Verbose" />
    </switches>
  </system.diagnostics>
</configuration>

When we run our application on Debug mode, we can see that the Output window will show our log data:

image

We can take it further and configure different listeners for different switches. The following configuration will enable TextWriterTraceListener for LoggingSample.MyCustomMiddleware SourceSwitch:

<configuration>
  <system.diagnostics>
    <switches>
      <add name="Microsoft.Owin" value="Verbose" />
    </switches>

    <sharedListeners>
      <add name="console" type="System.Diagnostics.ConsoleTraceListener" />
    </sharedListeners>

    <trace autoflush="true" />
    
    <sources>
      <source name="Microsoft.Owin">
        <listeners>
          <add name="console" />
        </listeners>
      </source>

      <source name="LoggingSample.MyCustomMiddleware">
        <listeners>
          <add name="file" 
               type="System.Diagnostics.TextWriterTraceListener" 
               initializeData="traces-MyCustomMiddleware.log" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
</configuration>

Now we can see that our middleware’s logs will only be written into traces-MyCustomMiddleware.log file:

image

I think this post should give you a pretty good understanding of how Katana’s logging infrastructure has been set up and works under the hood. I plain on writing a few more posts on this logging infrastructure. So, stay tuned. Also, as I get used to the concepts of OWIN, I started to think that this logging infrastructure is more fitting as an OWIN extension (just like the SendFile extension) rather than being tied to Katana.

The sample I used here also available on GitHub inside my OwinSamples repository.

Tags