Do I need a Global.asax.cs file at all if I'm using an OWIN Startup.cs class and move all configuration there?

74,358

Solution 1

Startup.Configuration gets called slightly later than Application_Start, but I don't think the difference will matter much in most cases.

I believe the major reasons we kept the other code in Global.asax are:

  1. Consistency with previous versions of MVC. (That's where everybody currently expects to find this code.)
  2. Ability to add other event handlers. In Global.asax, you can handle other methods like Session_Start and Application_Error.
  3. Correctness in a variety of authentication scenarios. The Startup.Configuration method is only called if you have Microsoft.Owin.Host.SystemWeb.dll in your bin directory. If you remove this DLL, it will silently stop calling Startup.Configuration, which could be hard to understand.

I think the third reason is the most important one we didn't take this approach by default, since some scenarios don't include having this DLL, and it's nice to be able to change authentication approaches without invalidating the location where unrelated code (like route registration) is placed.

But if none of those reasons apply in your scenario, I think you'd be fine using this approach.

Solution 2

For those looking for the complete steps: If you are looking to create a OWIN based, IIS hosted web API, these steps should get you there:

  1. File -> New -> Project
  2. In the dialogue, Installed -> templates -> Other Project types -> Visual Studio Solutions -> Blank Solution targeting .NET 4.6
  3. On the solution, right click, add Project -> Web -> ASP.NET Web Application (targeting .NET 4.6)

    3.1 Now In the ASP.NET 4.5 templates, choose Empty as the template

    3.2 This creates a blank solution with two nuget packages:

    Microsoft.CodeDom.Providers.DotNetCompilerPlatform v 1.0.0
    Microsoft.Net.Compilers v 1.0.0
    
  4. Install the following packages:

    Install-Package Microsoft.AspNet.WebApi.WebHost -Version 5.2.3
    Install-Package Microsoft.AspNet.WebApi -Version 5.2.3
    Install-Package WebApiContrib.Formatting.Razor 2.3.0.0
    

For OWIN:

Install-Package Microsoft.Owin.Host.SystemWeb 
Install-Package Microsoft.AspNet.WebApi.OwinSelfHost    

Then add Startup.cs with Configuration method:

[assembly:OwinStartup(typeof(namespace.Startup))]
public class Startup
    {
        /// <summary> Configurations the specified application. </summary>
        /// <param name="app">The application.</param>
        public static void Configuration(IAppBuilder app)
        {
            var httpConfiguration = CreateHttpConfiguration();

            app
                .UseWebApi(httpConfiguration);
        }

        /// <summary> Creates the HTTP configuration. </summary>
        /// <returns> An <see cref="HttpConfiguration"/> to bootstrap the hosted API </returns>
        public static HttpConfiguration CreateHttpConfiguration()
        {
            var httpConfiguration = new HttpConfiguration();
            httpConfiguration.MapHttpAttributeRoutes();

            return httpConfiguration;
        }
}

Now add a class that inherits from ApiController, annotate it with RoutePrefix attribute and the action method with Route + HttpGet/PutPost (representing the Http verb you're after) and you should be good to go

Solution 3

This is my understanding of how starting/hosting a web application evolved as it's all pretty confusing to follow. A small summary:

1. Classic ASP.NET: Write only the application code to run in the last step of the mandatory IIS pipeline

2. ASP.NET with OWIN: Configure a .NET webserver and write your application code. No longer directly coupled to IIS, so you're no longer forced to use it.

3. ASP.NET Core: Configure both the host and the webserver to use and write your application code. No longer mandatatory to use a .NET webserver if you target .NET Core instead of the full .NET Framework.


Now I'll go a bit more into detail of how it works and which classes are used to start the application:

Classic ASP.NET

Classic ASP.NET applications have the Global.asax file as entry point. These applications can only be run in IIS and your code gets executed at the end of the IIS pipeline (so IIS is responsible for CORS, authentication... before your code even runs). Since IIS 7 you can run your application in integrated mode which integrates the ASP.NET runtime into IIS. This enables your code to configure functionality which wasn't possible before (or only in IIS itself) such as url rewriting in the Application_Start event of your Global.asax file or use the new <system.webserver> section in your web.config file.

ASP.NET with OWIN

First of all OWIN is not a library but a specification of how .NET web servers (for example IIS) interact with web applications. Microsoft themselves have an implementation of OWIN called project Katana (distributed through several different NuGet packages). This implementation provides the IAppBuilder interface you encounter in a Startup class and some OWIN middleware components (OMC's) provided by Microsoft. Using IAppBuilder you basically compose middleware in a plug-and-play way to create the pipeline for the webserver (in addition to only the ASP.NET pipeline in IIS7+ as in the point above) instead of being tied to the IIS pipeline (but now you use a middleware component for CORS, a middleware component for authentication...). Because of this, your application is not specifically coupled to IIS anymore and you can run it on any .NET Webserver, for example:

  • The OwinHost package can be used to self-host your application with a Katana webserver.
  • The Microsoft.Owin.Host.SystemWeb package is used to host your OWIN application in IIS7+ in integrated mode, by subscribing your middleware to the correct lifetime events internally.

The thing that makes everything so confusing is that Global.asax is still supported together with the OWIN Startup class, while they can both do similar things. For example you could implement CORS in Global.asax and authentication using OWIN middleware which becomes really confusing.

My rule of thumb is to remove the Global.asax file alltogether in favor of using Startup whenever I need to add OWIN.

ASP.NET Core

ASP.NET Core is the next evolution and now you can target either .NET Core or the full .NET Framework. When you target .NET Core you can run your application on any host which supports the .NET Standard. This means you are no longer restricted to a .NET webserver (as in the previous point), but can host your application in Docker containers, a linux webserver, IIS...

The entry point for an ASP.NET Core web application is the Program.cs file. There you configure your host and again specify your Startup class where you configure your pipeline. Using OWIN (by using the IAppBuilder.UseOwin extension method) is optional, but fully supported.

Share:
74,358

Related videos on Youtube

John Smith
Author by

John Smith

Updated on July 08, 2022

Comments

  • John Smith
    John Smith almost 2 years

    Let's say for example in a brand new ASP.NET MVC 5 application made from the MVC with Individual Accounts template, if I delete the Global.asax.cs class and move it's configuration code to Startup.cs Configuration() method as follow, what are the downsides?

    public partial class Startup
    {
         public void Configuration(IAppBuilder app)
         {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
    
            ConfigureAuth(app);
        }
    }
    

    The upsides for me is that when upgrading ASP.NET 4 applications to ASP.NET 5 and using pieces that now must be configured in the Startup.cs class, I'm not doing dependency injection and other configuration in two different classes that seem related to starting up, and configuration.

    • harvzor
      harvzor almost 5 years
      AreaRegistration.RegisterAllAreas(); Caused an error for me as this method is not allowed to be used during startup like this, only in Application_Start. However, my application is an API and this method is apparently only useful for MVC applications: stackoverflow.com/questions/18404637/…
  • Boris Lipschitz
    Boris Lipschitz almost 10 years
    Another advantage of using Startup.Configuration() is you can easily host your website using owin self-host with just 1 line of code: WebApp.Start<Startup>("localhost:3001/") asp.net/web-api/overview/hosting-aspnet-web-api/… It's especially handy for writing integration tests
  • user510101
    user510101 about 9 years
    In order to prevent the "silently stop calling Startup.Configuration" side-effect, you can add a web.config appSettings key "owin:appStartup" that explicitly specifies the type to be used for OWIN startup, instead of relying on the name convention lookup. This is also handy for supporting different configurations for different environments (dev/test/prod)
  • Pluc
    Pluc over 8 years
    +1 for #3. I wanted a lean start to a Web API so I created an empty template ASP.NET website and added WebApi.Owin nuget package. I wrongfully expected the dependency to include everything to run on IIS. No idea why I thought that since I wanted an Owin startup to uncouple the IIS dependency in the first place.
  • yyardim
    yyardim about 7 years
    Thank you @dotnetguy!!! I have been trying to get rid of Global.asax completely but wasn't able to. Finally following your steps, it worked for me. The missing part in my case was the the reference to Install-Package Microsoft.AspNet.WebApi.OwinSelfHost Once I add that to my api, I was able to delete the global.asax.
  • Alexander Derck
    Alexander Derck almost 7 years
    @yyardim I think the OwinSelfHost doesn't have much to do with global.asax file, it only gives you the option to host your application outside of iis, in a windows service for example
  • Dairo
    Dairo about 6 years
    @dotnetguy Install-Package WebApiContrib.Formatting.Razor 2.3.0.0 shows an install-package not found error. Got installing of this package working with Install-Package WebApiContrib.Formatting.Razor 2.3.0, so without the last.0
  • Dairo
    Dairo about 6 years
    @dotnetguy The [assembly:OwinStartup(typeof(namespace.Startup))] part must be above the namespace part otherwise it gives the following error Assembly and module attributes must precede all other elements defined in a file except using clauses and extern alias declarations.