Simple.Web: OWIN and Katana

In the 0.9 release of Simple.Web we announced improved support for running Simple.Web with an OWIN-compatible web-server, particular focus on compatibility with the upcoming release of Katana v2. We also introduced a new self-hosting package aimed at reducing boiler-plate code associated with bootstrapping.

ON A SIDE NOTE

OWIN is a standard interface specification born into the community by Benjamin van der Veen ~2010 to provide a common “glue” between server, and framework or module. Katana is Microsoft’s own implementation of an OWIN-compatible web server with accompanying set of modules.

OWIN Compatibility

Simple.Web was built around OWIN and it’s delegate method signature, but it relied on it’s sister projects Fix and Flux for assurance. With the emergence of viable server alternatives (such as Katana) we found areas for improvement, mainly where interpretation of the specification could result in an incompatibility.

Not strictly part of the specification the community has grown towards a set of common conventions:

Builder helpers

It’s common for extension methods to be provided to reduce boilerplate code and complexity. In the case of Simple.Web we have introduced UseSimpleWeb().

Previously
1
2
3
using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;

app.Use(new Func<AppFunc, AppFunc>(ignoreNextApp => (AppFunc)Simple.Web.Application.Run);
Now
1
app.UseSimpleWeb();

Startup.Configuration

OWIN-compatible servers often scan for a Startup class with a Configuration method as an application entry point. To reduce boilerplate code we have introduced Simple.Web.OwinSupport.OwinStartupBase.

Minimal
1
public class Startup : OwinStartupBase { }
AppBuilder
1
2
3
4
5
6
7
8
public class Startup : OwinStartupBase
{
    public Startup() : base(builder => {
      builder.UseErrorPage();
      builder.UseWelcomePage("/owin");
      builder.UseSimpleWeb();
    });
}

Katana Compatibility

Katana supports different approaches for hosting your application. We have built a set of sample projects to illustrate SimpleWeb’s compatibility. Find below some example code snippets.

Self-Hosting

To reduce boiler-plate code when bootstraping your server from a console project we have introduced a new self-hosting package that uses Katana v2.

Minimal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace OwinConsoleHost
{
    using System;

    using Simple.Web.Hosting.Self;

    internal class Program
    {
        private static void Main(string[] args)
        {
            new OwinSelfHost().Run();
        }
    }
}
Options
1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace OwinConsoleHost
{
    using System;

    using Simple.Web.Hosting.Self;

    internal class Program
    {
        private static void Main(string[] args)
        {
            new OwinSelfHost().Run("localhost", port: 3333, ssl: false);
        }
    }
}
AppBuilder
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace OwinConsoleHost
{
    using System;

    using Simple.Web.Hosting.Self;

    internal class Program
    {
        private static void Main(string[] args)
        {
          new OwinSelfHost(
                builder =>
                    {
                        builder.UseErrorPage();
                        builder.UseSimpleWeb();
                    })
                    .Run();
        }
    }
}
Custom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
namespace OwinConsoleHost
{
    using System;

    using Simple.Web.Hosting.Self;

    internal class Program
    {
        private static void Main(string[] args)
        {
            var host = new OwinSelfHost();

            using (host.Start(hostname: "localhost", port: 3333, ssl: false))
            {
                Console.WriteLine("Listening at http://localhost:3333. Press CTRL-C to stop.");

                Console.CancelKeyPress += (sender, eventArgs) => Console.WriteLine("Stopping.");

                while (true)
                {
                }
            }
        }
    }
}

Library (using OwinHost.exe)

You can contain your application within a library project (assembly) and use Katanas’ OwinHost.exe to bootstrap it. The easiest way to do this is by adding NuGet package OwinHost-mono to your solution.

Startup.cs
1
2
3
4
5
6
7
8
9
10
[assembly: Microsoft.Owin.OwinStartup(typeof(OwinWebHost.Startup))]

namespace OwinWebHost
{
    using Simple.Web.OwinSupport;

    public class Startup : OwinStartupBase
    {
    }
}

To enable F5 run from Visual Studio you will need to add a StartAction to the bottom of your csproj file:

.csproj
1
2
3
4
  <PropertyGroup>
    <StartAction>Program</StartAction>
    <StartProgram>$(ProjectDir)../packages/OwinHost-mono.2.0.0-rtw-20815-004/tools/OwinHost.exe</StartProgram>
  </PropertyGroup>

Note You need to make sure your output path does not contain the project configuration (e.g. “debug”) as OwinHost.exe doesn’t like it. I have raised this with the Katana team but without resolution.

Web Application

Support for Web Application project types comes via web.config and Microsoft.Owin.OwinStartup assembly attribute. Your web application will run on top of SystemWeb, including interactive debugging.

Startup.cs
1
2
3
4
5
6
7
8
9
10
[assembly: Microsoft.Owin.OwinStartup(typeof(OwinWebHost.Startup))]

namespace OwinWebHost
{
    using Simple.Web.OwinSupport;

    public class Startup : OwinStartupBase
    {
    }
}

web.config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?xml version="1.0"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <appSettings>
    <add key="owin:Configuration" value="KatanaWebApplication2.Startup.Configuration, KatanaWebApplication2" />
    <add key="owin:SetCurrentDirectory" value="true" />
    <add key="webpages:Enabled" value="false" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpHandlers>
      <clear />
      <add verb="*" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb" />
    </httpHandlers>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules>
      <remove name="RewriteModule" />
      <remove name="OutputCache" />
      <remove name="Session" />
      <remove name="WindowsAuthentication" />
      <remove name="FormsAuthentication" />
      <remove name="DefaultAuthentication" />
      <remove name="RoleManager" />
      <remove name="UrlAuthorization" />
      <remove name="FileAuthorization" />
      <remove name="AnonymousIdentification" />
      <remove name="Profile" />
      <remove name="UrlMappingsModule" />
      <remove name="ServiceModel-4.0" />
      <remove name="UrlRoutingModule-4.0" />
      <remove name="ScriptModule-4.0" />
    </modules>
    <handlers>
      <clear />
      <add name="Owin" verb="*" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb" />
    </handlers>
    <security>
      <requestFiltering allowDoubleEscaping="true" allowHighBitCharacters="true">
        <fileExtensions allowUnlisted="true">
          <clear />
        </fileExtensions>
        <hiddenSegments>
          <clear />
        </hiddenSegments>
        <verbs allowUnlisted="true" />
      </requestFiltering>
    </security>
  </system.webServer>
</configuration>

That’s all for now folks! :–)

Comments