Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC WebAPI Data Annotation Error Message Empty String

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).

enter image description here

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.. "
}
like image 841
vesuvious Avatar asked Oct 30 '22 20:10

vesuvious


1 Answers

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; }
}
like image 135
Chris Terry Avatar answered Nov 24 '22 11:11

Chris Terry