Reputation: 473
I have an ASP.NET application and I'm trying to use ModelState.IsValid
to return error messages if the query is flawed. I tried something like this:
[HttpGet]
[Route("")]
[Route("{id:int}")]
public IQueryable<ToDoTable> Get(int id = -1)
{
if (!ModelState.IsValid)
{
var errorList = (from item in ModelState
where item.Value.Errors.Any()
select item.Value.Errors[0].ErrorMessage).ToList();
return errorList.AsQueryable();
}
else
{
if (id == -1)
return db.ToDoTables;
else
return db.ToDoTables.Where(lt => lt.ID == id);
}
}
However, the problem is that errorList
is of type string
and the function is expecting a return type of ToDoTable
, a class that I made. How do I get the correct return type? Or do I need to change the function's expectations? Do I have to add the method into the class instead (not even sure that would work)?
When ModelState.IsValid
is true, the function is returning class objects with information gathered from the database I'm querying and outputs it as JSON. Example:
[
{
"ID": 11,
"Title": "this is a test",
"Description": "this is specifically to test the put method",
"Due": null,
"Completed": true
},
{
"ID": 15,
"Title": "date test",
"Description": "datetime format",
"Due": "2015-08-10T02:41:29",
"Completed": true
}
]
Upvotes: 0
Views: 107
Reputation: 36081
An approach that I have used in the past is to return an HttpResponseMessage from the method.
This will allow you to return an 'error' type (for example https://datatracker.ietf.org/doc/html/draft-nottingham-http-problem) and appropriate response code (e.g. 400).
Your function then becomes:
[HttpGet]
[Route("")]
[Route("{id:int}")]
public HttpResponseMessage Get(int id = -1)
{
if (!ModelState.IsValid)
{
var errorList = (from item in ModelState
where item.Value.Errors.Any()
select item.Value.Errors[0].ErrorMessage).ToList();
return Request.CreateResponse(HttpStatusCode.BadRequest, errorList);
}
else
{
var tables = (id == -1) ? db.ToDoTables : db.ToDoTables.Where(lt => lt.ID == id);
return Request.CreateResponse(HttpStatusCode.OK, tables);
}
}
This means that you can cope with differing response types and statuses without throwing HttpResponseExceptions.
Upvotes: 1
Reputation: 151594
Think from your consumers. How are you going to communicate and document this? "This API call returns a Foo, except for in cases where it returns Bar".
That is possible, but then you need to either change the return type to an IHttpActionResult
or throw new HttpResponseException
.
(Arguably) better would be to introduce a response container with nullable properties, something like this:
public class ApiResponse<T>
{
public bool Success { get; set; }
public int? RecordCount { get; set; }
public T Content { get; set; }
public ErrorDetail Error { get; set; }
}
This way all your operations can benefit from being statically-typed (think unit tests) and return success and failure in the same way.
Related: Handle ModelState Validation in ASP.NET Web API, Best practice to return errors in ASP.NET Web API, Storing result of Web API call into Generic type class,
Upvotes: 0