简体   繁体   中英

How to solve chicken-egg dependency resolution for MVC controller with Authorize attribute applied?

I have this situation where the fact that the user is not logged in is preventing the construction of my controller's dependencies.

[Authorize]
class MyController : Controller
{
    public MyController(MyService service)
    {
    }
}

class MyService
{
    public MyService()
    {
        // requires information which only
        // becomes known after the user logs in
    }
}

My question is: can I do something to cause the MVC framework to first look at the Authorize attribute and then resolve the controller instance?

The above would be much more preferable to me than either of the following:

  • Changing MyService to be able to handle being created before user log in
  • Injecting Func
  • Switching to service location

Ideally, I'd like to flip a switch in the MVC framework that says, "before you resolve the controller, check that you're actually going to use it and not toss it out due to lack of authorization and direct anyway..."

I have this situation where the fact that the user is not logged in is preventing the construction of my controller's dependencies.

That's the root of your problem.

// requires information which only becomes known after the user logs in

This means that the constructor of that service does too much. Constructors should not do more than store the incoming dependencies. This way you can compose object graphs with confidence .

The building of object graphs should in general be static. This means that the resolved object graph should not change based on runtime conditions (there are exceptions, but this is a good rule of thumb). It shouldn't matter whether or not a user is authorized or not, the service class should still be composed and injected. This means that authorization and loading of data is done at a later point in time; the moment that the request is actually executed (which is directly after the object graph is composed).

Your problem is that you don't really understand how the MVC Request pipeline works.

The first thing you have to realize is that Attributes are, in essence, designed to match up with identical events in the controller base class. There is an OnAuthorization method in Controller, and this is called either just before or just after the attributes OnAuthorization method is called.

So, in order for it to call both methods at roughly the same time, that means the Controller class must have been constructed to do so. What's more, a lot of other stuff goes on before Authorization filters, such as model binding, because your authorization filter may need information from the model to make its decision.

I suggest you check out this pipline chart.

https://www.simple-talk.com/dotnet/.net-framework/an-introduction-to-asp.net-mvc-extensibility/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM