It looks like you're having more trouble with Validation than errors/exceptions so I'll say a bit about both.
Validation
Controller actions should generally take Input Models where the validation is declared directly on the model.
public class Customer
{
[Require]
public string Name { get; set; }
}
Then you can use an ActionFilter
that automatically sends validation messages back to the client.
public class ValidationActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var modelState = actionContext.ModelState;
if (!modelState.IsValid) {
actionContext.Response = actionContext.Request
.CreateErrorResponse(HttpStatusCode.BadRequest, modelState);
}
}
}
For more information about this check out http://ben.onfabrik.com/posts/automatic-modelstate-validation-in-aspnet-mvc
Error handling
It's best to return a message back to the client that represents the exception that happened (with relevant status code).
Out of the box you have to use Request.CreateErrorResponse(HttpStatusCode, message)
if you want to specify a message. However, this ties the code to the Request
object, which you shouldn't need to do.
I usually create my own type of "safe" exception that I expect the client would know how to handle and wrap all others with a generic 500 error.
Using an action filter to handle the exceptions would look like this:
public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
var exception = context.Exception as ApiException;
if (exception != null) {
context.Response = context.Request.CreateErrorResponse(exception.StatusCode, exception.Message);
}
}
}
Then you can register it globally.
GlobalConfiguration.Configuration.Filters.Add(new ApiExceptionFilterAttribute());
This is my custom exception type.
using System;
using System.Net;
namespace WebApi
{
public class ApiException : Exception
{
private readonly HttpStatusCode statusCode;
public ApiException (HttpStatusCode statusCode, string message, Exception ex)
: base(message, ex)
{
this.statusCode = statusCode;
}
public ApiException (HttpStatusCode statusCode, string message)
: base(message)
{
this.statusCode = statusCode;
}
public ApiException (HttpStatusCode statusCode)
{
this.statusCode = statusCode;
}
public HttpStatusCode StatusCode
{
get { return this.statusCode; }
}
}
}
An example exception that my API can throw.
public class NotAuthenticatedException : ApiException
{
public NotAuthenticatedException()
: base(HttpStatusCode.Forbidden)
{
}
}
ModelState
. – Daniel LittleHttpResponseException
class which takes two parameters mentioned in your post -HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)
i.e.HttpResponseException(string, HttpStatusCode)
– RBT