Why the identifier does not load when resolving WebApi, but when resolving Mvc controllers

I use Autofac for the Inversion of Control container that is configured this way

public void Configuration(IAppBuilder app) { configureIoC(app); configureAuth(app); } void configureIoC(IAppBuilder app) { var b = new ContainerBuilder(); //... b.Register(c => HttpContext.Current?.User?.Identity ?? new NullIdentity()).InstancePerLifetimeScope(); var container = b.Build(); app.UseAutofacMiddleware(container); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container); } 

I believe that the fact that this is Autofac compared to any other container is probably not related to what I use. Here, the key line is the configuration of any IIdentity dependency that needs to be torn from HttpContext.Current .

I use it so that I have access to the current user anywhere, wherever I am.

 public interface ICurrentUser { Task<AppUser> Get(); } public class CurrentUserProvider : ICurrentUser { public async Task<AppUser> Get() => await users.FindByNameAsync(currentLogin.GetUserId()); public CurrentUserProvider(AppUserManager users, IIdentity currentLogin) { this.users = users; this.currentLogin = currentLogin; } } 

I used this template for past projects and it works great. I am applying it to an existing project now and I see a very strange thing.

  • When an Asp.net Mvc controller depends on ICurrentUser , everything works fine
  • When the WebApi controller receives an instance of ICurrentUser , the Get operation fails because the IIdentity instance IIdentity not been parsed from the cookie and has not yet been loaded into it ( AuthenticationType == null )! Oddly enough, if I paused the debugger after creating an instance of the WebApi controller, I can click HttpContext.Current.User.Identity and see that AuthenticationType == "Cookie" and all the complaints are there.

What this leads me to conclude is that something happens in the following order

  • If this is an api web route, the web api controller creates an instance
  • Asp.Net identifier populates the current HttpContext Identity
  • If this is an mvc route, the mvc controller creates an instance
  • Any action taken

This, of course, makes no sense!

So the questions are:

  • Is my conclusion about the order of things in the pipeline correct?
  • How can I control his work? Why did it work on other projects, but did it cause problems here? Can I connect something in the wrong order?

Please do not suggest creating an IdentityProvider for late resolution of IIdentity . I understand how I can solve the problem, that I do not understand why this is happening, and how to manage the pipelined order of things.

+7
asp.net-mvc asp.net-web-api asp.net-identity
source share
1 answer

I changed your code a bit since I do not have NullIdentity() , and your CurrentUserProvider did not compile here.

I installed these packages:

  • Autofac
  • Autofac.Owin
  • Autofac.Owin
  • Autofac.Mvc5
  • Autofac.Mvc5.Owin
  • Autofac.WebApi2
  • Autofac.WebApi2.Owin

My Startup.cs looks like this:

 public partial class Startup { public void Configuration(IAppBuilder app) { configureIoC(app); ConfigureAuth(app); } void configureIoC(IAppBuilder app) { var b = new ContainerBuilder(); //... b.RegisterType<CurrentUserProvider>().As <ICurrentUser>().InstancePerLifetimeScope(); b.Register(c => HttpContext.Current.User.Identity).InstancePerLifetimeScope(); b.RegisterControllers(typeof(MvcApplication).Assembly); b.RegisterApiControllers(typeof(MvcApplication).Assembly); var x = new ApplicationDbContext(); b.Register<ApplicationDbContext>(c => x).InstancePerLifetimeScope(); b.Register<UserStore<ApplicationUser>>(c => new UserStore<ApplicationUser>(x)).AsImplementedInterfaces().InstancePerLifetimeScope(); b.RegisterType<ApplicationUserManager>().InstancePerLifetimeScope(); b.RegisterType<ApplicationSignInManager>().InstancePerLifetimeScope(); var container = b.Build(); app.UseAutofacMiddleware(container); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container); } } 

Your ICurrentUser Material:

 public interface ICurrentUser { Task <ApplicationUser> Get(); } public class CurrentUserProvider : ICurrentUser { private ApplicationUserManager users; private IIdentity currentLogin; public async Task<ApplicationUser> Get() { return await users.FindByNameAsync(currentLogin.GetUserId()); } public CurrentUserProvider(ApplicationUserManager users, IIdentity currentLogin) { this.users = users; this.currentLogin = currentLogin; } } 

Therefore Global.asax:

 public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); } } 

My HomeController , which is pretty simple:

 public class HomeController : Controller { private ICurrentUser current; public HomeController(ICurrentUser current) { this.current = current; } public ActionResult Index() { var user = current.Get(); if (user == null) throw new Exception("user is null"); return View(); } } 

... and finally, a simple ApiController, which I refer to by typing localhost / api / TestApi / 5 :

 public class TestApiController : ApiController { private ICurrentUser current; public TestApiController(ICurrentUser current) { this.current = current; } public string Get(int id) { var user = current.Get(); if (user == null) throw new Exception("user is null"); return ""; } } 

If I am just starting a project (without even logging in), I get a GenericIdentity object to support the IIdentity interface, look at this:

Debugging

And when I find (F11) in the Get() method, IIdentity is set correctly using this GenericIdentity , because in fact no one is registered in the application. That's why I think you really don't need this NullableIdentity.

enter image description here

Try to compare your code with mine and fix yours so that we can see if it works, and then you will find out what was the real cause of the problem, and not just fix it (we developers love to know why something just got the job) .

+1
source share

All Articles