问题
Are there any ways to set the order of execution on web api action filters registered with Autofac? Currently, if I register the following:
builder.Register(x => new MyFirstAttribute(x.Resolve<IMyService>())).AsWebApiActionFilterFor<ApiController>().InstancePerRequest();
builder.Register(x => new MySecondAttribute(x.Resolve<IMyService>())).AsWebApiActionFilterFor<ApiController>().InstancePerRequest();
it is 'unknown' which will be executing first and second. Even if I'd create a new FilterProvider which orders them in a specific way it will not work due to removal of any custom IFilterProvider and a private ActionDescriptorFilterProvider.
回答1:
There is currently no way to manually specify the order in which registered filters run.
Filters get resolved in the same way other dependencies get resolved using the IEnumerable<T>
implicit relationship type. This happens in the AutofacWebApiFilterProvider. As with regular filters, it's more complex than just "run in XYZ order" - there's controller vs. action scoping to take into account as well.
So, say you registered these:
builder.RegisterType<LoggingFilter>()
.AsWebApiActionFilterFor<ValuesController>()
.InstancePerApiRequest();
builder.RegisterType<AuthenticationFilter>()
.AsWebApiActionFilterFor<ValuesController>()
.InstancePerApiRequest();
builder.RegisterType<ErrorFilter>()
.AsWebApiActionFilterFor<ValuesController>(c => c.Get(default(int)))
.InstancePerApiRequest();
builder.RegisterType<RoundingFilter>()
.AsWebApiActionFilterFor<ValuesController>(c => c.Get(default(int)))
.InstancePerApiRequest();
Web API filters run controller level then action level; Autofac filters run in reverse registration order. If someone calls the Get
action on the ValuesController
the filters will run:
- AuthenticationFilter
- LoggingFilter
- RoundingFilter
- ErrorFilter
However, it's sometimes not as straightforward as that, since if you use an extension like PreserveExistingDefaults
it internally changes the order of registrations to put the PreserveExistingDefaults
registration last.
That sort of registration ordering complexity with handling defaults and so forth is why I can't point you to a line of code.You can look at the CollectionRegistrationSource which is responsible for resolving the IEnumerable<IActionFilter>
collections as part of the filter provider. You can also look at the filter provider to see how things happen.
If you need to manually specify order, you'll have to write your own extension to the AutofacWebApiFilterProvider
or, if extension doesn't work, roll your own. If you get it working well in a nice fluent manner, we'd be happy to take a pull request.
来源:https://stackoverflow.com/questions/35797079/autofac-iautofacactionfilter-execution-order-for-web-api-2