Reputation: 3078
I have the following view model:
public class EventViewModel
{
[Required(ErrorMessage = "type can not be empty")]
[JsonProperty("type")]
[DisplayName("type")]
public string Type { get; set; }
[Required(ErrorMessage = "date can not be empty")]
[JsonProperty("date")]
[DisplayName("date")]
public int Timestamp { get; set; }
[JsonProperty("data")]
public JObject Data { get; set; }
}
and the following controller action:
[Route("/api/v1.0/events")]
[HttpPost]
public async Task<IActionResult> Events([FromBody] List<EventViewModel> viewModel)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
I expect the following JSON:
[
{
"type" : "open",
"date" : 1567673607,
"data" : {
"message_id" : "lalalalala"
}
}
]
But what if a client will send me just:
[]
empty array?
I would like to show validation message. How I can do that? Is it possible?
Maybe the explanation of the problem is not so clear or I don't understand something. I'll try to fix it.
If I have this kind of JSON:
{
"items" :[
{
...
},
...
]
}
Then it's ok. Not problem. I can write:
public class EventViewModelList
{
[Required]
List<EventViewModel> EventViewModels {get; set;}
}
But my JSON is just array of objects. SO, I can't.
And I can to do something like:
public async Task<IActionResult> Events([Required][FromBody] List<EventViewModel> viewModel)
Because it does not work. Put validation into the controller? No (( Controller - is controller. Validation - is validation.
I think that I need attribute. But controller action level attribute. Like:
[Route("/api/v1.0/events")]
[NotEmptyListOfViewModels]
[HttpPost]
public async Task<IActionResult> Events([FromBody] List<EventViewModel> viewModel)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
Am I right?
Upvotes: 0
Views: 1905
Reputation: 12715
You could write a custom model binder like below:
NotEmptyListOfViewModels
public class NotEmptyListOfViewModels:IModelBinder
{
public async Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
//Get command model payload (JSON) from the body
String valueFromBody;
using (var streamReader = new StreamReader(bindingContext.HttpContext.Request.Body))
{
valueFromBody =await streamReader.ReadToEndAsync();
}
var modelInstance = JsonConvert.DeserializeObject<List<EventViewModel>>(valueFromBody);
if(modelInstance.Count==0)
{
bindingContext.ModelState.AddModelError("JsonData", "The json is null !");
}
bindingContext.Result = ModelBindingResult.Success(modelInstance);
}
}
Events action
[Route("/api/v1.0/events")]
[HttpPost]
public async Task<IActionResult> Events([ModelBinder(BinderType = typeof(NotEmptyListOfViewModels))]List<EventViewModel> viewModel)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return Ok();
}
Upvotes: 1
Reputation: 32109
You can do as follows:
[Route("/api/v1.0/events")]
[HttpPost]
public async Task<IActionResult> Events([FromBody] List<EventViewModel> viewModel)
{
if(viewModel == null || viewModel.Count == 0)
{
ModelState.AddModelError("","List can not be empty or null");
}
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
..............
}
Upvotes: 0