-1

I have a problem where I have passed two models into a view model. In a particular view I only want to check validation for two properties, one from each model in the view model.

However both models contain other properties each with their own data annotations, which means the form won't submit until all annotations have been satisfied even though they aren't on the form.

So I need to find a way to only check validation for specific properties in the two models, but still save the whole object to the database if it passes the validation check.

Code example

Models

public class FirstModel
{
    public int Id { get; set; }
    [Required]
    public string Prop2 { get; set; }
    [Required]
    public DateTime Prop3 { get; set; }
}

public class SecondModel
{
    public int Id { get; set; }
    [Required]
    public string Prop2 { get; set; }
    [Required]
    public int Prop3 { get; set; }
}

public class ThirdModel
{
    public int Id { get; set; }

    [Required]
    public FirstModel FirstModel { get; set; }
    [Required]
    public SecondModel SecondModel { get; set; }
}

View Model

public class ThirdFormViewModel
{
    // maybe I can do something here?
    public FirstModel FirstModel { get; set; }
    public SecondModel SecondModel { get; set; }
}

Controller Post Action

[HttpPost]
public ActionResult CreateThirdModel(ThirdModel newThirdModel)
{
    var firstModel = _context.FirstModels.Single(c => c.Id == newThirdModel.Id);

    var secondModel = _context.SecondModels.Single(c => c.Id == newThirdModel.SecondModel.Id);

    if (!ModelState.IsValid)
    {
        var viewModel = new ThirdFormViewModel
        {
            FirstModel = firstModel,
            SecondModel = secondModel
        };
        return View("ThirdModelForm", viewModel);

    }

    var thirdModel = new ThirdModel
    {
        FirstModel = firstModel,
        SecondModel = secondModel,
    };

    _context.ThirdModels.Add(thirdModel);
    _context.SaveChanges();

    return RedirectToAction("Index");
}

View

@model MyProject.ViewModels.ThirdFormViewModel

@using (Html.BeginForm()
{
    <div class="form-group">
        @Html.TextBoxFor(m => m.FirstModel.Prop2)
    </div>
    <div class="form-group">
        @Html.TextBoxFor(m => m.SecondModel.Prop3)
    </div>
    <button type="submit" class="btn btn-primary">Save</button>
}
  • Create a view model containing only the properties you want in the view - refer [What is ViewModel in MVC?](https://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc) (and view models do not contain data models) –  Mar 04 '18 at 05:14

3 Answers3

2

You could use ModelState.Remove to remove a property to being validated.

As you third view model is containing the property of other two models so property names should be like FirstModel.Prop2, this could further be checked in debugger through ModelState.Values

Example:

ModelState.Remove("FirstModel.Prop2");
ModelState.Remove("SecondModel.Prop2"); 
Kundan Singh Chouhan
  • 13,952
  • 4
  • 27
  • 32
0

you could just remove the ModelState.IsValid check and validate the data yourself. if you only need to validate 2 properties, that looks like the simpler approach

michael berezin
  • 1,146
  • 7
  • 8
0

If it were me, I would create multiple view models instead of passing the objects directly so you have more control over what your doing for scenarios like this. I typically try to create view models for all data being passed. It seems like you are having to map a lot of entities, but it keeps the entity models from getting cluttered. You have control to validate anything you need form the View because the DTO object is not being shared anywhere else. You can leave the data annotations in the Entity objects to be used for Entity Framework.

Some times you might want to make an object required on view model, but not in Entity or something like that.

If your objects are large, you could use AutoMapper to help map objects to make less work on your end as well.

View Model

public class FirstViewModel
{
    public int Id { get; set; }
    public string Prop2 { get; set; }
    public DateTime Prop3 { get; set; }
}

public class SecondViewModel
{
    public int Id { get; set; }
    public string Prop2 { get; set; }
    public int Prop3 { get; set; }
}

public class ThirdFormViewModel
{
    public FirstViewModel FirstModel { get; set; }
    public SeconViewdModel SecondModel { get; set; }
}
Brandon Turpy
  • 883
  • 1
  • 10
  • 32