简体   繁体   中英

How can I modify my view model to check validation for only specific properties?

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

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

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM