Was wondering if it is possible to use Model.IsValid with an ASP.NET Core Web API that takes in a JSON body as [FromBody] object from the controller argument.
Or should I just write my own validation methods? What is the direction to go in? How do I approach validation for this style of Web API, that really doesn't use MVC or Blazor; it just takes in GET and POST requests from a client UI web module (more than likely).
Granted this API is created to be agnostic framework wise, in the sense that it doesn't expect a model to be coming from a view... And I didn't come up with this design, so I am unfortunately stuck with it. We basically take in the raw JSON and use Newtonsoft methods to parse the request body into a C# class (DTO, COJO or whatever you want to call it).
- Should I just write my own validation methods somewhere in the project?
- Is there a third-party library out there that allows me to annotate my parameters in my classes...similar to the model validation concept/mechanism.
- Or is there a pattern or best practice to handle this type of ASP.NET Core Web API? I have always been taught that you should do parameter/field validation in the UI as well as the middleware / API / webservice level.
Here is a basic example of how a controller method looks in the project I am working on:
[HttpPost]
[Route("SubmitNewRecord")]
public ActionResult SubmitNewRecord([FromBody] object PostValues)
{
ExampleAPI.Model.MyInfo submitNewRecordDataRequest = null;
if (PostValues != null)
{
// Newtonsoft.Json.Linq;
JObject PostObject = (JObject)PostValues;
// Converting the raw incoming object PostValues to MyInfo class object:
submitNewRecordDataRequest = JsonConvert.DeserializeObject<ExampleAPI.Model.MyInfo>(PostObject.ToString());
}
else
{
response.ResultCode = "-12";
response.ResultMessage = "Incoming message was empty (null) - " + DateTime.Now;
_logger.LogCritical("Incoming message was empty (null)- " + DateTime.Now);
return new JsonResult(response);
}
// HERE I would like to use Model.IsValid...
// just putting a Model.IsValid check here is not working obviously.
if (ModelState.IsValid)
{
// Do stuff with the new MyInfo DTO (submitNewRecordDataRequest)
}
else
{
// throw error and send special response message.
}
}
Here is a sample data transfer object (DTO), I call it this because we aren't using Entity Framework, or any other ORM framework; just grabbing stored procedures from a database.
using System.ComponentModel.DataAnnotations;
namespace MyApi.DTOs
{
public class MyInfo
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public decimal Price { get; set; }
[Range(0, 999)]
public double Weight { get; set; }
[Required]
[StringLength(1000)]
public string Annotation{ get; set; }
}
}
Anyway... I don't know what the original designer was thinking, and he didn't document a specific approach to do object validation in the API. What is the best practice for an API using Newtonsoft like this? Apologies, I am new to this style of API...and I am probably using some of the wrong terminology.
Also this is the way we send posts, Its old school and yeah there is probably a better way:
$.ajax({
url: url,
type: 'POST',
headers: { "X-CSRF": "1" },
async: true,
cache: false,
data: data,
dataType: "json",
contentType: "application/json; charset=utf-8",
timeout: tmout,
success: fsuccess,
error: ferror
});
Note that the type is JSON and the contentType is: application/json; charset charset=utf-8...might make a difference.
I would suggest to make a more generic approach as have a base controller to make all error responses same:
then in your controller
and
now. with this request:
the response would be