My problem statement is same as this question i.e., use an injected service in attribute/filter. I have tried the solution given by B Z and following is my code along the lines of solution given.
//marker attribute
public class AuthorizeViewAttribute : Attribute { }
//filter
public class AuthorizeViewFilter : IAuthorizationFilter
{
private readonly IAccessRightsService _iAccessRightService;
public AuthorizeViewFilter(IAccessRightsService iAccessRightService)
{
_iAccessRightService = iAccessRightService;
}
public void OnAuthorization(AuthorizationContext filterContext)
{
RoleFeature roleFeature = _iAccessRightService.GetRoleFeatures();
if (roleFeature.IsView)
{
//redirect to controller
}
}
}
Following is the ninject binding I use:
this.BindFilter<AuthorizeViewFilter>(System.Web.Mvc.FilterScope.Controller, 0)
.WhenControllerHas<AuthorizeViewAttribute>();
I do not need any parameter in attribute, so I figured I do not need to use WithConstructorArgument as mentioned in this answer
But my filter never gets called. I put a default constructor in AuthorizeViewAttribute , debugged and found that the control jumps to default constructor in AuthorizeViewAttribute and continues with the controller method.
I cannot find any solution to this. Any suggestions?
Short story : You seem to be trying to use MVC filter and MVC binding on a webapi controller. That's why it does not work.
Long story : first create a webapi filter provider ( note, you will need Ninject.Extensions.Factories package to have Func<AuthorizeViewFilter>
resolved by Ninject)
public class AuthorizeViewFilterProvider : System.Web.Http.Filters.IFilterProvider
{
private readonly Func<AuthorizeViewFilter> _authorizeViewFilterFactory;
public AuthorizeViewFilterProvider(Func<AuthorizeViewFilter> authorizeViewFilterFactory)
{
this._authorizeViewFilterFactory = authorizeViewFilterFactory;
}
public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
if(!actionDescriptor.GetCustomAttributes<AuthorizeViewAttribute>().Any())
return Enumerable.Empty<FilterInfo>();
return new[]
{
new FilterInfo(this._authorizeViewFilterFactory(), FilterScope.Action)
};
}
}
then create a webapi filter
public class AuthorizeViewFilter : System.Web.Http.Filters.IAuthorizationFilter
{
private readonly IAccessRightsService _iAccessRightService;
public AuthorizeViewFilter(IAccessRightsService iAccessRightService)
{
_iAccessRightService = iAccessRightService;
}
public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(
HttpActionContext actionContext,
CancellationToken cancellationToken,
Func<Task<HttpResponseMessage>> continuation)
{
RoleFeature roleFeature = _iAccessRightService.GetRoleFeatures();
if (roleFeature.IsView)
{
return continuation();
}
else
return Task.FromResult(actionContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Access denied"));
}
}
then, bind the FilterProvider in your binding setup :
this.Bind<System.Web.Http.Filters.IFilterProvider>().To<AuthorizeViewFilterProvider>();
来源:https://stackoverflow.com/questions/48642507/webapi-custom-filter-with-injected-interface-in-constructor-does-not-get-called