OWIN Startup Class Detection

This tutorial shows how to configure which OWIN startup class is loaded. For more information on OWIN, see An Overview of Project Katana. This tutorial was written by Rick Anderson ( @RickAndMSFT ), Praburaj Thiagarajan, and Howard Dierking ( @howard_dierking ).

Prerequisites

Visual Studio 2017

OWIN Startup Class Detection

Every OWIN Application has a startup class where you specify components for the application pipeline. There are different ways you can connect your startup class with the runtime, depending on the hosting model you choose (OwinHost, IIS, and IIS-Express). The startup class shown in this tutorial can be used in every hosting application. You connect the startup class with the hosting runtime using one of the these approaches:

  1. Naming Convention: Katana looks for a class named Startup in namespace matching the assembly name or the global namespace.

  2. OwinStartup Attribute: This is the approach most developers will take to specify the startup class. The following attribute will set the startup class to the TestStartup class in the StartupDemo namespace.

    [assembly: OwinStartup(typeof(StartupDemo.TestStartup))]
    

    The OwinStartup attribute overrides the naming convention. You can also specify a friendly name with this attribute, however, using a friendly name requires you to also use the appSetting element in the configuration file.

  3. The appSetting element in the Configuration file: The appSetting element overrides the OwinStartup attribute and naming convention. You can have multiple startup classes (each using an OwinStartup attribute) and configure which startup class will be loaded in a configuration file using markup similar to the following:

    <appSettings>  
      <add key="owin:appStartup" value="StartupDemo.ProductionStartup" />
    </appSettings>
    

    The following key, which explicitly specifies the startup class and assembly can also be used:

    <add key="owin:appStartup" value="StartupDemo.ProductionStartup, StartupDemo" />
    

    The following XML in the configuration file specifies a friendly startup class name of ProductionConfiguration.

    <appSettings>  
      <add key="owin:appStartup" value="ProductionConfiguration" />       
    </appSettings>
    

    The above markup must be used with the following OwinStartup attribute which specifies a friendly name and causes the ProductionStartup2 class to run.

    [assembly: OwinStartup("ProductionConfiguration", typeof(StartupDemo.ProductionStartup2))]
    
    namespace StartupDemo
    {
        public class ProductionStartup
        {
            public void Configuration(IAppBuilder app)
            {
                app.Run(context =>
                {
                    string t = DateTime.Now.Millisecond.ToString();
                    return context.Response.WriteAsync(t + " Production OWIN App");
                });
            }
        }
        public class ProductionStartup2
        {
            public void Configuration(IAppBuilder app)
            {
                app.Run(context =>
                {
                    string t = DateTime.Now.Millisecond.ToString();
                    return context.Response.WriteAsync(t + " 2nd Production OWIN App");
                });
            }
        }
    }
    
  4. To disable OWIN startup discovery add the appSetting owin:AutomaticAppStartup with a value of "false" in the web.config file.

    <add key="owin:AutomaticAppStartup" value="false" />
    

Create an ASP.NET Web App using OWIN Startup

  1. Create an empty Asp.Net web application and name it StartupDemo. - Install Microsoft.Owin.Host.SystemWeb using the NuGet package manager. From the Tools menu, select NuGet Package Manager, and then Package Manager Console. Enter the following command:

    Install-Package Microsoft.Owin.Host.SystemWeb
    
  2. Add an OWIN startup class. In Visual Studio 2017 right-click the project and select Add Class.- In the Add New Item dialog box, enter OWIN in the search field, and change the name to Startup.cs, and then select Add.

    Screenshot of Add new item dialog.

    The next time you want to add an Owin Startup class, it will be in available from the Add menu.

    Screenshot of Add menu to add an Owin startup class.

    Alternatively, you can right-click the project and select Add, then select New Item, and then select the Owin Startup class.

    Screenshot of Select the Owin Startup class.

  • Replace the generated code in the Startup.cs file with the following:

    using System;
    using System.Threading.Tasks;
    using Microsoft.Owin;
    using Owin;
    using System.IO;
    
    //[assembly: OwinStartup(typeof(StartupDemo.Startup))]
    
    namespace StartupDemo
    {
       public class Startup
       {
          public void Configuration(IAppBuilder app)
          {
             app.Use((context, next) =>
             {
                TextWriter output = context.Get<TextWriter>("host.TraceOutput");
                return next().ContinueWith(result =>
                {
                   output.WriteLine("Scheme {0} : Method {1} : Path {2} : MS {3}",
                   context.Request.Scheme, context.Request.Method, context.Request.Path, getTime());
                });
             });
    
             app.Run(async context =>
             {
                await context.Response.WriteAsync(getTime() + " My First OWIN App");
             });
          }
    
          string getTime()
          {
             return DateTime.Now.Millisecond.ToString();
          }
       }
    }
    

    The app.Use lambda expression is used to register the specified middleware component to the OWIN pipeline. In this case we are setting up logging of incoming requests before responding to the incoming request. The next parameter is the delegate ( Func < Task > ) to the next component in the pipeline. The app.Run lambda expression hooks up the pipeline to incoming requests and provides the response mechanism.

    Note

    In the code above we have commented out the OwinStartup attribute and we're relying on the convention of running the class named Startup .- Press F5 to run the application. Hit refresh a few times.

    Screenshot of the runtime application.

    Note: The number shown in the images in this tutorial will not match the number you see. The millisecond string is used to show a new response when you refresh the page. You can see the trace information in the Output window.

    Screenshot of the output window.

Add More Startup Classes

In this section we'll add another Startup class. You can add multiple OWIN startup class to your application. For example, you might want to create startup classes for development, testing and production.

  1. Create a new OWIN Startup class and name it ProductionStartup.

  2. Replace the generated code with the following:

    using System;
    using System.Threading.Tasks;
    using Microsoft.Owin;
    using Owin;
    
    [assembly: OwinStartup(typeof(StartupDemo.ProductionStartup))]
    
    namespace StartupDemo
    {
        public class ProductionStartup
        {
            public void Configuration(IAppBuilder app)
            {
                app.Run(context =>
                {
                    string t = DateTime.Now.Millisecond.ToString();
                    return context.Response.WriteAsync(t + " Production OWIN App");
                });
            }
        }
    }
    
  3. Press Control F5 to run the app. The OwinStartup attribute specifies the production startup class is run.

    Screenshot of production startup class.

  4. Create another OWIN Startup class and name it TestStartup.

  5. Replace the generated code with the following:

    using System;
    using System.Threading.Tasks;
    using Microsoft.Owin;
    using Owin;
    
    [assembly: OwinStartup("TestingConfiguration", typeof(StartupDemo.TestStartup))]
    
    namespace StartupDemo
    {
        public class TestStartup
        {
            public void Configuration(IAppBuilder app)
            {
                app.Run(context =>
                {
                    string t = DateTime.Now.Millisecond.ToString();
                    return context.Response.WriteAsync(t + " Test OWIN App");
                });
            }
        }
    }
    

    The OwinStartup attribute overload above specifies TestingConfiguration as the friendly name of the Startup class.

  6. Open the web.config file and add the OWIN App startup key which specifies the friendly name of the Startup class:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <appSettings>
        <add key="owin:appStartup" value="TestingConfiguration" />
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5" />
      </system.web>
    </configuration>
    
  7. Press Control F5 to run the app. The app settings element takes precedent, and the test configuration is run.

    Screenshot of test configuration.

  8. Remove the friendly name from the OwinStartup attribute in the TestStartup class.

    [assembly: OwinStartup(typeof(StartupDemo.TestStartup))]
    
  9. Replace the OWIN App startup key in the web.config file with the following:

    <add key="owin:appStartup" value="StartupDemo.TestStartup" />
    
  10. Revert the OwinStartup attribute in each class to the default attribute code generated by Visual Studio:

    [assembly: OwinStartup(typeof(StartupDemo.Startup))]
    [assembly: OwinStartup(typeof(StartupDemo.ProductionStartup))]
    [assembly: OwinStartup(typeof(StartupDemo.TestStartup))]
    

    Each of the OWIN App startup keys below will cause the production class to run.

    <add key="owin:appStartup" value="StartupDemo.ProductionStartup" />
    <add key="owin:appStartup" value="StartupDemo.ProductionStartup, StartupDemo" />
    <add key="owin:appStartup" value="StartupDemo.ProductionStartup.Configuration, StartupDemo" />
    

    The last startup key specifies the startup configuration method. The following OWIN App startup key allows you to change the name of the configuration class to MyConfiguration .

    <add key="owin:appStartup" value="StartupDemo.ProductionStartup2.MyConfiguration" />
    

Using Owinhost.exe

  1. Replace the Web.config file with the following markup:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
       <appSettings>
          <add key="owin:appStartup" value="StartupDemo.Startup" />
          <add key="owin:appStartup" value="StartupDemo.TestStartup" />
       </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5" />
      </system.web>
    </configuration>
    

    The last key wins, so in this case TestStartup is specified.

  2. Install Owinhost from the PMC:

    Install-Package OwinHost
    
  3. Navigate to the application folder (the folder containing the Web.config file) and in a command prompt and type:

    ..\packages\Owinhost<Version>\tools\Owinhost.exe
    

    The command window will show:

    C:\StartupDemo\StartupDemo>..\packages\OwinHost.2.0.0\tools\Owin
    Host.exe
    Starting with the default port: 5000 (http://localhost:5000/)
    Started successfully
    Press Enter to exit
    
  4. Launch a browser with the URL http://localhost:5000/.

    Screenshot of launching a browser with the localhost URL.

    OwinHost honored the startup conventions listed above.

  5. In the command window, press Enter to exit OwinHost.

  6. In the ProductionStartup class, add the following OwinStartup attribute which specifies a friendly name of ProductionConfiguration.

    [assembly: OwinStartup("ProductionConfiguration", 
               typeof(StartupDemo.ProductionStartup))]
    
  7. In the command prompt and type:

    ..\packages\OwinHost.2.0.0\tools\OwinHost.exe ProductionConfiguration
    

    The Production startup class is loaded. Screenshot of Production startup class.

    Our application has multiple startup classes, and in this example we have deferred which startup class to load until runtime.

  8. Test the following runtime startup options:

    ..\packages\OwinHost.2.0.0-rc1\tools\OwinHost.exe StartupDemo.TestStartup
    ..\packages\OwinHost.2.0.0-rc1\tools\OwinHost.exe "StartupDemo.TestStartup,StartupDemo"
    ..\packages\OwinHost.2.0.0-rc1\tools\OwinHost.exe StartupDemo.TestStartup.Configuration
    ..\packages\OwinHost.2.0.0-rc1\tools\OwinHost.exe "StartupDemo.TestStartup.Configuration,StartupDemo"