ASP.NET Core Pitfalls - Action Constraint Order

Introduction

When we have more than one action method in MVP or Web API that can match a given request, the request may fail or land on an unwanted method. By default, a number of items is used to figure out which method to call:

  • The HTTP verb
  • The action method name
  • The route template
  • The action method parameters
  • The request content type

An action constaint may be needed to select the right one; an action constraint is an implementation of IActionConstraint, and is normally added through an attribute or a convention. Some examples of built-in action constrains include:

If you want to build your own, you should inherit from ActionMethodSelectorAttribute and implement IsValidForRequest.

Problem

Sometimes, however, just applying an action constraint is not enough, usually because the request matches more than one constraint. One example is with subsets of a given content type, the [Consumes] will also validate against those.

What we then need is to define the order by which we want the constraints checked, where the most "unusual" should go first. This is achieved through the Order property of IActionConstraint or the Order property of HttpMethodAttribute; the smaller order is executed first.

An example using [HttpPatch]:

[HttpPatch]
[Consumes("application/json")]
public IActionResult PatchJson([FromBody] Payload payload)
{            
    //...
}

[HttpPatch(Order = -1000)]
[Consumes("application/merge-patch+json")]
public IActionResult PatchMergePatchJson([FromBody] Payload payload)
{ //... }

When a request is made using "application/json" content-type, the first method matches; when using "application/merge-patch+json", the second does. In this case, the problem is that "application/merge-patch+json" is treated as a subset of "application/json".

Conclusion

Because ASP.NET Core is so flexible, it's usually easy to fix this kind of problems, once we know what they are. Stay tuned for more!

Comments

Popular posts from this blog

OpenTelemetry with ASP.NET Core

ASP.NET Core Middleware

.NET Cancellation Tokens