sming
sming

Reputation: 811

System.Web.Http.Filters.ActionFilterAttribute must be in same project as controller?

I have a System.Web.Http.ApiController-derived controller:

[LoggingFilterApi]
public class BaseController : ApiController
{
     public IHttpActionResult Ads();
}

with the filter defined as follows:

using System.Web.Http.Controllers;
using System.Web.Http.Filters;

namespace pecom.Common.Filters
{
    public class LoggingFilterApiAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext ctx)
        {
            var msg = ctx.ActionDescriptor.ControllerDescriptor.ControllerType.Name + "." + ctx.ActionDescriptor.ActionName +
                "(" + ctx.Request.RequestUri.ToString();

            ILog logger = LogManager.GetLogger(ctx.ActionDescriptor.ControllerDescriptor.ControllerType);
            logger.Info(msg);
            base.OnActionExecuting(ctx);
        }
    }
}

When LoggingFilterApiAttribute.cs is part of the controller's .csproj, OnActionExecuting is called as expected. However, if LoggingFilterApiAttribute.cs is moved to a different .csproj (to facilitate code reuse), OnActionExecuting is not called as expected. Weird.

Anyone seen this? For the time being I'm duplicating filters across our projects, which is somewhat suboptimal. This is with ASP.NET MVC 5.2.

Cheers, Pete

Upvotes: 8

Views: 10945

Answers (2)

Wasp
Wasp

Reputation: 3425

You most likely have a mismatch in Web Api 2 versions. No matter which version of MVC, your controller is a Web Api one, so you have to pay attention to Web Api related assemblies.

I'm pretty sure that, if you check the version of System.Web.Http in both your MVC project and your class library, they'll be different, and therefore the discovery mechanism is not able to find your custom filter. Just fix the problem by making them match and it should work.

One simple way to fix that is to reference the latest Web Api 2 package (Microsoft.AspNet.WebApi.Core) in your class library, and to upgrade the same package in your MVC project to make them match (or by messing with assembly redirects if you like so). If, for example, you just copied the code into the class library and then used something like Resharper to resolve the references, it might most likely have picked version 4.x of System.Web.Http from GAC, instead of version 5.x that you need here.

I tried what you did and it reproduced your same issue, and this procedure solved it.

Upvotes: 7

christophe vialatte
christophe vialatte

Reputation: 224

I managed to make it work in a few steps :

  1. Create an MVC application
  2. Create an empty class library
  3. add the MVC framework to the class library using nuget
  4. add reference to System.Web to the class Library project
  5. Copy your code in a new class of the class library
  6. Remove code related the logger for testing purpose
  7. Replace HttpActionContext ctx by ActionExecutingContext filterContext
  8. Replace ctx.Request.RequestUri.ToString() by filterContext.HttpContext.Request.Url
  9. Reference the Class library project
  10. Add the the filter to the home controller

Job done

Upvotes: 1

Related Questions