0

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?

Update

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?

2
  • You could create your own validation attribute by implementing ValidationAttribute and add the attribute to your property. Commented Jan 27, 2020 at 14:08
  • Does this answer your question? ModelState is valid with null model Commented Jan 27, 2020 at 14:09

2 Answers 2

1

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();
}
Sign up to request clarification or add additional context in comments.

Comments

0

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);
    }

    ..............
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.