Reputation: 39384
On an Web API controller I have the following:
if (!ModelState.IsValid)
return BadRequest();
BadRequest: https://msdn.microsoft.com/en-us/library/system.web.http.apicontroller_methods%28v=vs.118%29.aspx
I would like to create a custom error message to pass errors as json.
Something like:
if (!ModelState.IsValid)
return ModelHasErrors(errors);
How can I create a custom error response?
Upvotes: 0
Views: 5902
Reputation: 3217
The simplest way is
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ModelState);
I am used to use special object, that represents error response. I can add my specific (translated) message, status code, etc.
public class ErrorModel
{
public ErrorModel(HttpStatusCode statusCode, string message)
{
StatusCode = (int)statusCode;
Message = message;
ValidationErrors = new Dictionary<string, ModelErrorCollection>();
}
public ErrorModel(HttpStatusCode statusCode)
{
StatusCode = (int)statusCode;
ValidationErrors = new Dictionary<string, ModelErrorCollection>();
}
public string Message { get; set; }
public int StatusCode { get; set; }
public Dictionary<string, ModelErrorCollection> ValidationErrors { get; set; }
public Exception Exception { get; set; }
}
Then I have extension for CreateCustomResponse
public static class ApiExtensions
{
public static HttpResponseMessage CreateCustomResponse(this HttpRequestMessage request, HttpStatusCode statusCode, string errorMessage)
{
var errorMessageModel = new ErrorModel(statusCode, errorMessage);
return request.CreateResponse(statusCode, errorMessageModel);
}
public static HttpResponseMessage CreateCustomResponse(this HttpRequestMessage request, HttpStatusCode statusCode, Exception exception, string errorMessage = "")
{
if (string.IsNullOrEmpty(errorMessage) && exception != null)
{
errorMessage = exception.Message;
}
var errorMessageModel = new ErrorModel(statusCode, errorMessage)
{
Exception = exception
};
return request.CreateResponse(statusCode, errorMessageModel);
}
public static HttpResponseMessage CreateCustomResponse(this HttpRequestMessage request,
HttpStatusCode statusCode, ModelStateDictionary modelState, string errorMessage = "")
{
if (string.IsNullOrEmpty(errorMessage))
{
errorMessage = ApiValidationMessages.GeneralModelIsNotValid;
}
var errorMessageModel = new ErrorModel(statusCode, errorMessage);
foreach (var error in modelState.Where(x => x.Value.Errors != null && x.Value.Errors.Any()))
{
errorMessageModel.ValidationErrors.Add(error.Key.Replace("model.", ""), error.Value.Errors);
}
return request.CreateResponse(statusCode, errorMessageModel);
}
}
And finally in my controllers I just call:
return Request.CreateCustomResponse(HttpStatusCode.NotFound, ApiHttpResultMessages.NotFound);
You can find inspiration in my CodePlex project Web API Design: https://webapidesign.codeplex.com/
Upvotes: 3
Reputation: 4450
You could return a HttpResponseMessage
using an object containing your error messages (in this example errors
) as content:
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new ObjectContent(typeof(ErrorClass), errors, new JsonMediaTypeFormatter())
};
More information about how to return action results can be found here.
You can obviously reuse the above code by creating a method and call it like in your example: ModelHasErrors(errors)
.
However, if you often find yourself returning the same response, a nice option would be to create an custom exception filter which would return the same response whenever ModelState.IsValid
is false.
Upvotes: 0
Reputation: 39025
You can return directly whichever object you want, and it will be serialized as JSON. It can even be an anonymous class object created with new { }
On The client side you have to check if you've received a regurlar response, or the error object, which can be easyly donde by checking the existence of some property of your custom error object.
Upvotes: 0