Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use a custom constraint with a HttpMethodConstraint in ASP.NET MVC routing?

I have a controller that only accepts a POST on this URL:

POST http://server/stores/123/products

The POST should be of content-type application/json, so this is what I have in my routing table:

routes.MapRoute(null,
                "stores/{storeId}/products",
                new { controller = "Store", action = "Save" },
                new {
                      httpMethod = new HttpMethodConstraint("POST"),
                      json = new JsonConstraint()
                    }
               );

Where JsonConstraint is:

public class JsonConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        return httpContext.Request.ContentType == "application/json";
    }
}

When I use the route, I get a 405 Forbidden:

The HTTP verb POST used to access path '/stores/123/products' is not allowed

However, if I remove the json = new JsonConstraint() constraint, it works fine. Does anybody know what I'm doing wrong?

like image 312
Daniel T. Avatar asked Jan 28 '10 23:01

Daniel T.


People also ask

How do you add constraints in attribute routing?

We can apply the multiple constraints to a parameter by a colon (:) separator. [Route(URLPath/{parameterName: constrain:Constrain:….})] In the preceding example, the route will only be selected if the parameter id is an integer as well as a value of id greater than 1000.

What class would you create to implement a custom constraint for a route segment in ASP.NET Core?

Implement the IRouteConstraint Match method in ASP.NET Core To create a custom route constraint, you should create a class that extends the IRouteConstraint interface and implements its Match method.

Which is the syntax for custom routes in ASP.NET MVC?

aspx file Register Route method. //Custom Route With Regular Expression Constraints routes. MapRoute( "Blog", "Archive/{entrydate}", new { Controller = "Blog", action = "Archive" }, new { entryDate = @"\d{2}-\d{2}-\d{4}" });


1 Answers

I'd put this in a comment but there isn't enough space.

When writing a custom constraint it is very important to inspect the routeDirection parameter and make sure that your logic runs only at the right time.

That parameter tells you whether your constraint is being run while processing an incoming request or being run while someone is generating a URL (such as when they call Html.ActionLink).

In your case I think you want to put all your matching code in a giant "if":

public bool Match(HttpContextBase httpContext, Route route,
    string parameterName, RouteValueDictionary values,
    RouteDirection routeDirection) 
{
    if (routeDirection == RouteDirection.IncomingRequest) {
        // Only check the content type for incoming requests
        return httpContext.Request.ContentType == mimeType; 
    }
    else {
        // Always match when generating URLs
        return true;
    }
}
like image 77
Eilon Avatar answered Oct 28 '22 02:10

Eilon