How to install ASP.NET Web Api HTTP return code

I am using ASP.NET Web Api 2 framework and am using main route constraint as shown below.

    [Route("Number/{id:int:min(2):max(10)}")]
    public HttpResponseMessage GetNumber([FromUri] int id)
    {
        return (id > 0)
            ? Request.CreateResponse(HttpStatusCode.OK, id)
            : Request.CreateResponse(HttpStatusCode.PreconditionFailed);
    }

      

I would like to know when id conflicts with the above constraint, eg. 1 or 11, how can I override the default HTTP return code which is 404?

Many thanks.

+3


source to share


3 answers


You can create your own route constraint that checks the min, max values ​​as you wish, and optionally allow you to specify HttpStatusCode

in case the constraint is not met correctly.

public class RangeWithStatusRouteConstraint : IHttpRouteConstraint
{
    private readonly int _from;
    private readonly int _to;
    private readonly HttpStatusCode _statusCode;

    public RangeWithStatusRouteConstraint(int from, int to, string statusCode)
    {
        _from = from;
        _to = to;
        if (!Enum.TryParse(statusCode, true, out _statusCode))
        {
            _statusCode = HttpStatusCode.NotFound;
        }
    }

    public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values,
        HttpRouteDirection routeDirection)
    {
        object value;
        if (values.TryGetValue(parameterName, out value) && value != null)
        {
            var stringValue = value as string;
            var intValue = 0;

            if (stringValue != null && int.TryParse(stringValue, out intValue))
            {
                if (intValue >= _from && intValue <= _to)
                {
                    return true;
                }

                //only throw if we had the expected type of value
                //but it fell out of range
                throw new HttpResponseException(_statusCode);
            }
        }

        return false;
    }
}

      

Now you need to register it with the attribute mapping:

        var constraintResolver = new DefaultInlineConstraintResolver();
        constraintResolver.ConstraintMap.Add("rangeWithStatus", typeof(RangeWithStatusRouteConstraint));
        config.MapHttpAttributeRoutes(constraintResolver);

      



Now your route might look like this:

public class MyController : ApiController
{
    [Route("Number/{id:int:rangeWithStatus(2, 10, PreconditionFailed)}")]
    public HttpResponseMessage GetNumber([FromUri] int id)
    {
        return Request.CreateResponse(HttpStatusCode.OK, id);
    }
}

      

in this case Conflict

is the string representation of the enumeration HttpStatusCode.Conflict

, which is later cast to the enumeration value in the constraint.

With this setting, if the value falls outside the range [2, 10], the web API framework will respond with a 409 status code instead of the default 404.

+7


source


Remove the route constraint and check inside the method.

Constraints are used to determine if a route should be used at all, but you want to use a route that needs to be clicked, but change the status code if the input signal is outside some parameters.



[Route("Number/{id})] // No constraints
public HttpResponseMessage GetNumber([FromUri] int id)
{
    return (id > 1 && id < 11) // here you validate id range
        ? Request.CreateResponse(HttpStatusCode.OK, id)
        : Request.CreateResponse(HttpStatusCode.PreconditionFailed);
}

      

+5


source


I think the correct solution is to check the constraint inside the controller (as @aanund suggested). However, if you want to keep the route constraints and avoid conventions in your code, you can create another action controller with the same route but no constraints. If the constraints are not checked, a new action controller will be called:

[Route("Number/{id:int:min(2):max(10)}")]
public HttpResponseMessage GetNumber([FromUri] int id)
{
    Request.CreateResponse(HttpStatusCode.OK, id)
}

[Route("Number/{id}")]
public HttpResponseMessage GetNumber2([FromUri] int id)
{
    Request.CreateResponse(HttpStatusCode.PreconditionFailed);
}

      

+1


source







All Articles