autofac / Autofac

An addictive .NET IoC container
https://autofac.org
MIT License
4.5k stars 837 forks source link

WebAPI 5 (Autofac WebApi Integration 5) custom IAutofacActionFilter not assigned to a certain method #465

Closed alexmg closed 10 years ago

alexmg commented 10 years ago

From Rauber.M...@googlemail.com on October 30, 2013 17:48:34

What steps will reproduce the problem? 1. Create a new ApiController

  1. Create a new AuthorizationFilter using IAutofacAuthorizationFilter
  2. Create a new BypassFilter using IAutofacActionFilter
  3. Within the AuthorizationFilter check if the BypassFilter is set as a custom attribute on an action: if (actionContext.ActionDescriptor.GetCustomAttributes().Any()) { return; }
  4. Assign the AuthorizationFilter globally to the controller using builder.Register(x => new ApiAuthorizationFilterAttribute()) .AsWebApiAuthorizationFilterFor() .InstancePerApiRequest();
  5. Assign the BypassFilter to a certain method: builder.Register(x => new BypassApiKeyFilterAttribute()) .AsWebApiActionFilterFor(x => x.Get(default(string), default(bool))) .InstancePerApiRequest(); What is the expected output? What do you see instead? I except to bypass the apikey authorization, because the AuthorizationFilter checks for CustomAttributes, but does not find any. What version of Autofac are you using? On what version of .NET/Silverlight? Autofac 3.1.5 Autofac.WebApi5 ( http://www.nuget.org/packages/autofac.webapi5 ) .NET 4.5 Please provide any additional information below. Found this post here: http://alexmg.com/post/2012/09/01/New-features-in-the-Autofac-MVC-4-and-Web-API-(Beta)-Integrations.aspx and tried to do the same in my application.

You can see the code on GitHub: https://github.com/ManuelRauber/ShortUrl/tree/Bypass The relevant files are:

Bootstrap: https://github.com/ManuelRauber/ShortUrl/blob/Bypass/ShortUrl/Common/Bootstrap.cs#L36 # Api-Attribute: https://github.com/ManuelRauber/ShortUrl/blob/Bypass/ShortUrl/Common/ApiAuthorizationFilterAttribute.cs#L50 # Bypass-Attribute: https://github.com/ManuelRauber/ShortUrl/blob/Bypass/ShortUrl/Common/BypassApiKeyFilterAttribute.cs

Original issue: http://code.google.com/p/autofac/issues/detail?id=465

alexmg commented 10 years ago

From alex.meyergleaves on October 30, 2013 07:45:53

This issue was closed by revision fd6e9da7b0e9 .

Status: Fixed

alexmg commented 10 years ago

From alex.meyergleaves on October 30, 2013 08:03:51

I see what you are trying to achieve with the attributes.

The BypassApiKeyFilterAttribute is not an actual attribute so the reflection based GetCustomAttributes implementation will not find it. In the current Web API integration even if you did update the filter to derive from ActionFilterAttribute, unless you applied it to the action method as an attribute Web API would not find it.

I have added a fluent API to the ContainerBuilder for overriding filters at the controller or action level. The API works the same way you register filters. Under the hood it uses the new IOverrideFilter support.

In your ShortUrl project it would like this:

builder.Register(x => new ApiAuthorizationFilterAttribute()) .AsWebApiAuthorizationFilterFor() .InstancePerApiRequest();

builder.OverrideAuthorizationFilterFor(x => x.Get(default(string)));

builder.OverrideAuthorizationFilterFor(x => x.Get(default(string), default(bool)));

With this in place there is no need for your BypassApiKeyFilterAttribute. The ApiAuthorizationFilterAttribute will simply not be called for the matching actions (or controller if you like).

This is currently only available on the MyGet CI feed. https://www.myget.org/feed/autofac/package/Autofac.WebApi2 I am going to add the same thing to the MVC integration and will then push both packages to NuGet.org. If you could grab the package from MyGet and give it a test that would be appreciated.

alexmg commented 10 years ago

From Rauber.M...@googlemail.com on October 30, 2013 08:24:03

This works like a charm!

The BypassApiKeyFilterAttribute is not an actual attribute so the reflection based GetCustomAttributes implementation will not find it. In the current Web API integration even if you did update the filter to derive from ActionFilterAttribute, unless you applied it to the action method as an attribute Web API would not find it. <<<

Yes, zonk... I read it over and over again. It's mentioned in the documentation, but I just didn't got it. Was a bit late yesterday :)

Thank you for the fast patch!