Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A basic Katana application

0.00/5 (No votes)
20 Oct 2014 1  

Introduction

As we have seen in the previous article Katana is just a set of components that supports the OWIN specification and is used to create decoupled web applications.In a Katana application each component in the request pipeline can be easily replaced with another one.

There are types which helps build the different layers in the OWIN specification.There are types to start the host, launch the server , which will listen for and handle the request, and the types that represents the middleware components in the pipeline.

So for instance we can use the WebApp class to start the web server which will listen on a particular port and use the types to plug-in the different middleware components in the pipeline.

We will see what are the important types in Katana which helps build a decoupled web application. 

Some of the important types in a OWIN Katana application are :-

Startup Class

This class is used by the host to create the pipeline.It specifies the different components that will be part of the request pipeline.There are different ways in which we can specify the Startup class.

We can specify the Startup class to the runtime in the following three different ways.

  • Naming Convention based approach to specify the Startup class    We can name our startup class as Startup and it will be recognized by the runtime as the startup class.
  • Attribute based approach to specify the Startup class     We can specify the Startup class using the assembly attribute OwinStartup  in AssemblyInfo.cs                                                                                                  [assembly: OwinStartup(typeof(SampleApplication.OurStartupClass))]
  • Configuration based approach to specify the Startup class                                                                                 <add key="owin:appStartup" value="StartupNamespace.StartupClass" />                                                     We can specify the value as the name of the namespace followed by the name of the class.

The above three approaches to specify class name are applied in the mentioned order.So Configuration takes precedence over Attribute and Naming Convention.So even if we have a class named Startup we can specify another startup class name in the configuration file.

We will use the first approach and define a startup class and a Configuration method inside that class.

public class Startup
    {
        public void Configuration(IAppBuilder app)
        {

        }
    }

It’s Important to note that the method name should be Configuration otherwise we will get a runtime error that a method named configuration is not defined. We can verify this by renaming the method to configuration1(or any other name) and running the application. We get the below error as expected.

The Configuration method introduces us to another important type used in Katana the IAppBuilder Interface.

IAppBuilder Interface

As we can see above the IAppBuilder reference is getting passed to the Configuration method.IAppBuilder type contains methods to configure our application.

These methods are extension methods so they are available through different types which belongs to different assemblies. So we will need to add the proper assemblies to access these methods.If we see the definition of IAppBuilder,it does not define the Run() method since that is defined by the AppBuilderUseExtensions class.

The Run() method  is called by katana when it needs to process the  request for our application. When browser sends the request to our application, using the URL passed in the WebApp.Start() method ,this run method executes and we get the response message in the browser.

app.Run(owin => owin.Response.WriteAsync("Hello from owin test app"));

The input parameter to the Run method is a Func delegate. This Func delegate accepts an object of another useful type IOwinContext and returns a task.

IOwinContext Interface

The  IOwinContext reference which gets passed to the Run() method belongs to the  Microsoft.Owin namespace.It wraps the environment dictionary as mentioned in the OWIN specification apart from containing the properties for various environment properties.


IOwinContext type defines the following useful members

Request                   Includes request specific properties.  
Response                 Includes response specific properties.  
TraceOutput            Used to trace the response  
Authentication        Used to provide authentication  functioanlity in the           application  
Get<T>                  Used to se the value in the Environment  
Set<T>                   Used to get the value from the Environment  
Environment           The dictionary exposed by Owin to pass the values across the request pipeline  

Now as we know about the IAppBuilder and IOwin types we will implement the configuration method as below. In the lambda expression passed to the Run() method we will add a key in the owin Environment dictionary and then just display it's value in the browser.

app.Run(owin => {
                owin.Set<string>("firstname", "ashish");
                return owin.Response.WriteAsync(string.Format("Hello your {0} is {1}", 
                    "firstname",(string)owin.Get<string>("firstname")));

We have defined the Startup class and the Run method but it is not of much use until we tell the runtime to use it to configure the request pipeline.As we will be self hosting the application we will use another useful type WebApp Class.

WebApp Class

This type contains methods to load and start the web application.

WebApp class belongs to the Microsoft.Owin.Hosting namespace and contains the  overloaded Start () methods to load and start a web application.Though these methods can be used to start a web application they differ in the parameters and web application configuration they provide.

Start<Tstartup>()    Starts the WebApplication using the entry type we spcify in Tstartup.

Start<TStartup>(uri)   Starts the WebApplication using the entry type we spcify in Tstartup. and listen for requests on the uri passed as a parameter.

As both of the above methods returns an IDisposable reference ,we can call the methods in a using block.So whenever the control exits from our using() block our webapplication shuts down.

Below is the code which we can use start the http listener which listens for a request on the specified url and port. Startup is the class in which define the configuration information for our application. The configuration information allows Katana to create the request pipeline.

string uri = "http://localhost:2000";
WebApp.Start<Startup>(uri)

We will also need to define the Startup class which is passed as a paramter to the Start method above.

After the above line executes our application will start listening for the requests at the given url. Though we have used port 2000 here but we can use any available port.Below is the code to start the web server which we defined in the Main method of the console application.Now our web server has started and is listening for requests.

static void Main(string[] args)
        {
            string uri = "http://localhost:7990";
            using (WebApp.Start<Startup>(uri))
            {
                Console.WriteLine("Web server on {0} starting.", uri);
                Console.ReadKey();
                Console.WriteLine("Web server on {0} stopping.", uri);
            }
        }

As we have defined the StartUp class we will be able to execute our application ,otherwise if don't define the startup class we will get a compilation error complaining that the StartUp class is not defined. 

Now let us run the application by pressing F5.Once the application starts executing we will paste the following URL in the browser. This is the address on which our webserver is listening for requests as we have configured in the Main() method

http://localhost:2000

We will get the below response in the browser.

So now our web server is hosted in a console application ,listening for requests and also sending the response back to the browser.

Creating a Request Pipeline

In an Owin application it is normal to create a chain of components that form a request handling pipeline. The Run method we used can be used to plug-in a single middleware component .

As we have seen earlier static extension methods are defined for IAppBuilder.One such static method defined by this interface is Use which has two overloads.   

 public static IAppBuilder Use<T>(this IAppBuilder app, params object[] args);

and

public static IAppBuilder Use(this IAppBuilder app, Func<Microsoft.Owin.IOwinContext, Func<System.Threading.Tasks.Task>, System.Threading.Tasks.Task>

So instead of defining our middleware functionality using the lambda expression passed as a parameter to the run() method we will create a separate middleware class.This approcah is more useful as it empowers us to create a chain of middleware components.

Below we have defined a class called Middleware

 public class MiddlewareClass
        {
            private AppFunc _nextMiddleware;
            public MiddlewareClass(AppFunc nextMiddleware)
            {
                _nextMiddleware = nextMiddleware;
            }

            public async Task Invoke(IDictionary<string, object> environment)
            {
                Console.WriteLine("Hello OWIN");
                await _nextMiddleware(environment);
            }
        }

Before providing the implementation for the class it is important to note few things.

The Middleware class constructor expects a delegate which has IDictionary<String,Object> input type and returns a Task.This delegate represents the next middleware in pipeline

The method name in the middleware is Invoke.This is the method that is invoked in the middleware and it is from this method that we can call the next component in the request pipeline.

We can configure our application to use the above Middleware using the below

 public void Configuration(IAppBuilder app)
        {
            app.Use(typeof(MiddlewareClass));

        }

executing the application we get the below response.

Though we have a created a single middleware class but we can easily create a chain of middleware classes using this approach.

 

 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here