Do I Need a Global.Asax.Cs File at All If I'm Using an Owin Startup.Cs Class and Move All Configuration There

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

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.

Is there any way to configure owin startup.cs to be run before global asax application start?

With MVC 5, OWIN will always run after global.asax Application_Start(). That's because the MVC application hosts OWIN. It's far easier to let OWIN handle configurations and startups, with App_Start just for MVC registrations. So I recommend moving your container registrations and startups to Startup. Something like this:

public partial class Startup
{
public void Configuration(IAppBuilder app)
{
DependencyResolver.SetResolver(
new StructureMapDependencyResolver(IoC.Container));

IoC.Container.Configure(cfg =>
{
...
});

using (var container = IoC.Container.GetNestedContainer())
{
foreach (var task in container.GetAllInstances<IRunAtInit>())
{
task.Execute();
}

foreach (var task in container.GetAllInstances<IRunAtStartup>())
{
task.Execute();
}
}
}
}

Then, in the Application_BeginRequest, Application_EndRequest, and Application_Error, you access the container via the DependencyResolver. e.g.:

public void Application_BeginRequest()
{
foreach (var task in DependencyResolver.Current.GetServices<IRunOnEachRequest>())
{
task.Execute();
}
}

Notice there is no more Container property and subsequently no nested containers (except that one in startup). That's because your question is more nuanced than just pipeline timings. The container and transaction per request patterns are really about lifecyles (specifically Transient lifecycles) which, in ASP.NET, the container already knows to resolve per request. So you don't need to duplicate that effort. The StructureMap documentation explains it better than I can.

Side note: There is a PreApplicationStart attribute you can put on an assembly which indicates what method to run before Application_start, but because it's a static method, it's really only good for static configurations - which an IoC container is not.

No more Global.asax, but OWIN Startup.cs

You can move most of these lines unmodified into the Configuration method of your Startup class. Something like the following should do it:

public void Configuration(IAppBuilder appBuilder)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
config.Filters.Add(new ExceptionHandlingAttribute());
// move other lines over here
appBuilder.UseWebApi(config);
}

Shouldn't OwinStartupAttribute run before global.asax and Application_Start?

According to this answer it runs slightly after Application_Start. So if you, just like me need to run code before Application_Start, WebActivator is still the way to go I guess. Do I need a Global.asax.cs file at all if I'm using an OWIN Startup.cs class and move all configuration there?

How to configure SignalR with Global.asax instead of Startup.cs in ASP MVC?

You can mark which class in an assembly will be automatically used by Owin in the startup.

In my example, I declared it in the Startup and pointed to it using OwinStartup
e.g.

using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using System.Net;
[assembly: OwinStartup(typeof(YourProject.Startup))]

namespace YourProject
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
var hubConfiguration = new HubConfiguration
{
EnableDetailedErrors = true
};
app.MapSignalR(hubConfiguration);
}
}
}

If you are using Owin, you must use the Startup class instead of the Global.asax.

OWIN and Global.asax.cs file

I fix this problems. I just use other IOC container Unity

Here is an implementation of IDependencyResolver that wraps a Unity container.

public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;

public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}

public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}

public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}

public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}

public void Dispose()
{
container.Dispose();
}
}

WebApiConfig.cs

public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
container.RegisterType<IProductRepository, ProductRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);

// Other Web API configuration not shown.
}

Some controllers with use IoC containers:

public class ProductsController : ApiController
{
private IProductRepository _repository;

public ProductsController(IProductRepository repository)
{
_repository = repository;
}

// Other controller methods not shown.
}

Dependency Injection in ASP.NET Web API 2

Application_Start() & Application_End() methods are not fired in startup.cs class in asp.net MVC 5

You can manually add Global.asax to your project as mentioned here.

Otherwise, you can use Configuration(IAppBuilder app) or constructor in your Startup.cs. Configuration is called "slightly later" than Application_Start as mentioned in detail here.

Is there Application_End from Global.asax in Owin?

AppProperties, found in Microsoft.Owin.BuilderProperties, exposes the CancellationToken for OnAppDisposing.

You can get this token and register a callback to it

public class Startup
{
public void Configuration(IAppBuilder app)
{
var properties = new AppProperties(app.Properties);
CancellationToken token = properties.OnAppDisposing;
if (token != CancellationToken.None)
{
token.Register(() =>
{
// do stuff
});
}
}
}


Related Topics



Leave a reply



Submit