I have implemented an OWIN self-hosted webapi and am trying to use data annotations and an ActionFilterAttribute to return formatted errors to the user. I have set custom error messages on the data annotation but when I try to retrieve the message from the ModelState it is always an empty string (shown in image below).
Model:
public class JobPointer
{
[Required(ErrorMessage = "JobId Required")]
public Guid JobId { get; set; }
}
Filter:
public class ModelValidationFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ModelState.IsValid) return;
string errors = actionContext.ModelState.SelectMany(state => state.Value.Errors).Aggregate("", (current, error) => current + (error.ErrorMessage + ". "));
actionContext.Response = actionContext.Request.CreateErrorResponse(
HttpStatusCode.BadRequest, errors);
}
}
Endpoint:
[HttpPost]
public HttpResponseMessage DescribeJob(JobPointer jobId)
{
Job job = _jobhelper.GetJob(jobId.JobId);
return Request.CreateResponse(HttpStatusCode.OK, job);
}
Request Body:
{
}
Response:
Status Code: 400
{
"Message": ". "
}
If I change error.Message in ModelValidationFilter to error.Exception.Message I get back the default validation error:
Status Code: 400
{
"Message": "Required property 'JobId' not found in JSON. Path '', line 3, position 2.. "
}
I know this is an old question, but I just had this problem and found the solution myself.
As you no doubt discovered, as Guid is a non-nullable type [Required] produces an unfriendly error message (I assume because the JSON parser picks it up before actually getting the model validation).
You can get around this by making the Guid nullable...
public class JobPointer
{
[Required(ErrorMessage = "JobId Required")]
public Guid? JobId { get; set; }
}
... however, this is not a viable option in all cases (as in my case), so I ended up writing my own validation attribute that would check the property against it's Empty declaration...
public class IsNotEmptyAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
if (value == null) return false;
var valueType = value.GetType();
var emptyField = valueType.GetField("Empty");
if (emptyField == null) return true;
var emptyValue = emptyField.GetValue(null);
return !value.Equals(emptyValue);
}
}
You could then implement like...
public class JobPointer
{
[IsNotEmpty(ErrorMessage = "JobId Required")]
public Guid JobId { get; set; }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With