Search code examples
c#asp.net-mvc-4dispose

MVC4 WebApi Controller Post Action with Dispose Pattern causes Multiple Actions Found Exception


I think I've spotted a problem with the MVC4 WebApi Controller in conjunction with the Dispose Pattern. The problem is with the Post Action Method, the response is a description of the Exception:

Multiple actions were found that match the request:
Void Post(System.String) on type MVC4Api.Controllers.ValuesController
Void Dispose() on type MVC4Api.Controllers.ValuesController

The dispose pattern is sourced from this article. I've reduced the problem to just the boiler plate code below. Its worth pointing out that this problem does not occur with the Get method, I have confirmed it only with the Post method. Please try it out by Posting to the path /api/values.

public class ValuesController : ApiController
{
    public void Post([FromBody]string value)
    {
    }

    private bool _disposed;

    protected override void Dispose(bool disposing)
    {
        if (_disposed)
        {
            return;
        }

        _disposed = true;

        base.Dispose(disposing);

        if (disposing)
        {
            // dispose of dependencies
        }
    }

    public new void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

My question is how can I call the Post Method? And what is causing this problem?

EDIT: As the error is about routing I have added below the WebApiConfig which controls the routing. This is loaded as normal at start up in the Global.asax and has not changed since starting a new WebApi project.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

Solution

  • Its much easier to understand the solution when you correctly interpret the error message: When making the choice to the request, the WebApi Action Selector cannot decide between the Dispose() and Post() methods. (Which seems pretty daft in itself). So the error is effectively asking us to help make this decision for it.

    My preferred option is to use the NonActionAttribute class on the Dispose() Action method. This is a clear and transparent instruction to the Action Selector to not consider the Dispose method in deciding where to route the request.

    [NonAction]
    public new void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    

    The other option is to change the accessor of the Dipose() method to protected, but that's just not as obvious.