How to return ModelState with Forbidden status web api

719 views Asked by At

We can return ModelState with BadRequest from web api in following way:

return BadRequest(ModelState);

It provides following output:

{
    "Message": "The request is invalid.",
    "ModelState": {
        "property": [
            "error"
        ]
    }
}

How can I return the same output with Forbidden status?

I tried following method:

return Content(HttpStatusCode.Forbidden, ModelState);

But it returns:

{
    "property": {
        "_errors": [
            {
                "<Exception>k__BackingField": null,
                "<ErrorMessage>k__BackingField": "error"
            }
        ],
        "<Value>k__BackingField": null
    }
}

Json serializing ModelSate is also not returning the same thing. How can I use the serialization method used by BadRequest() method for ModelState with other status codes?

1

There are 1 answers

0
ctor On

You can achieve the desired output by using the ExecuteAsync method of InvalidModelStateResult (return type of BadRequest() method of ApiController) which actually serializes the ModelState.

So the idea is to create a new class which extends InvalidModelStateResult and override ExecuteAsync method to change the status code.

public class ModelStateResult : InvalidModelStateResult
{
    private readonly HttpStatusCode _status;

    public ModelStateResult(ModelStateDictionary modelState, ApiController controller, HttpStatusCode status) : base(modelState, controller)
    {
        _status = status;
    }

    public override Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = base.ExecuteAsync(cancellationToken).Result;
        response.StatusCode = _status;
        return Task.FromResult(response);
    }
}

Use it like:

return new ModelStateResult(ModelState, this, HttpStatusCode.Forbidden);    //this refers to ApiController here

I think this is just a work around, hope someone posts a better way to achieve it.

EDIT:

Without using InvalidModelStateResult:

public class ModelStateResult : IHttpActionResult
{
    public HttpStatusCode Status { get; }
    public ModelStateDictionary ModelState { get; }
    public HttpRequestMessage Request { get; }

    public ModelStateResult(HttpStatusCode status, ModelStateDictionary modelState, HttpRequestMessage request)
    {
        Status = status;
        ModelState = modelState;
        Request = request;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = Request.CreateErrorResponse(Status, ModelState);
        return Task.FromResult(response);
    }
}