3

Is it possible to place conditions on a ViewModel where data equals a specific value in one field within the entity framework, the required element or entire object is removed from the ViewModel before using TryValidateModel on the ViewModel?

I would like to remove HomeValue and PurchasePrice from the Model validation where OwnOrRent (model.OwnOrRent) is not equal to 1 or 9.

Model.cs

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

    [DisplayName("House Name or Number")]
    [StringLength(50)]
    public string HouseNameOrNumber { get; set; }

    [DisplayName("Post Town")]
    [StringLength(50)]
    public string PostTown { get; set; }

    [Required(ErrorMessage = "Own or Rent is Required")]
    [DisplayName("Own or Rent")]
    [StringLength(50)]
    public string OwnOrRent { get; set; }

    [Required(ErrorMessage = "Mortgage/Rent Amount is Required")]
    [DisplayName("Mortgage/Rent Amount")]
    [StringLength(50)]
    public string MortgageRent { get; set; }

    [Required(ErrorMessage = "Home Value is Required")]
    [DisplayName("Home Value")]
    [StringLength(50)]
    public string HomeValue { get; set; }

    [Required(ErrorMessage = "Purchase Price is Required")]
    [DisplayName("Purchase Price")]
    [StringLength(50)]
    public string PurchasePrice { get; set; }
}

HomeController.cs

public ActionResult Application(int id)
{
    var viewAddressModel = new Address();

    using (
        var dbEntities = new DbEntities(new EntityConnection(_df.DbEntities)))
    {
        var model = dbEntities.Applications.Single(e => e.Id == id);

        viewAddressModel.Id = Id;
        viewAddressModel.HouseNameOrNumber = model.HouseNameOrNumber;
        viewAddressModel.PostTown = model.PostTown;
        viewAddressModel.OwnOrRent = GetStatus(model.OwnOrRent);
        viewAddressModel.MortgageRent = model.MortgageRent.ToString();
        viewAddressModel.HomeValue = model.HomeValue;
        viewAddressModel.PurchasePrice = model.PurchasePrice;

        if (model.OwnOrRent != "1" || model.OwnOrRent != "9")
        {
            ModelState.Remove("HomeValue");
            ModelState.Remove("PurchasePrice");
        }

        if (!TryValidateModel(viewAddressModel))
        {
            return PartialView("Address", viewAddressModel);
        }
    }

    var vm = new ApplicationViewModel { Item = CreateApp(id) };

    return PartialView("Application", vm);
}

As you can see I have tried to use ModelState.Remove but this has no effect.

Any assistance with this would be much appreciated?

iggyweb
  • 2,373
  • 12
  • 47
  • 77
  • Remove really? Or you want them to be excluded from validation... – Tushar Gupta May 19 '15 at 09:17
  • There is no point in `ModelState.Remove("HomeValue");` - there are no values in `ModelState` at that point. And why are you calling `TryValidateModel` in a GET method? I suggest you do some research on `ModelState` to understand what it is and how it works. –  May 19 '15 at 09:23
  • The reason for TryValidateModel is to recheck old data that was stored pre MVC and prior to my involvement, to ensure any issues such as missing data are presented to the user requesting data to address the issue and rectify before carrying on with an application. – iggyweb May 19 '15 at 10:11
  • As for remove, I wish to turn off the validation, when model.OwnOrRent is not 1 or 9 as no data exists for HomeValue or PurchasePrice as it is not required. – iggyweb May 19 '15 at 10:13

2 Answers2

4

Based on your comments you want to populate a model from the database, then validate it (because its old data which may not be valid), but not display errors for HomeValue or PurchasePrice based on the value of OwnOrRent, in which case you need to call TryValidateModel first, then remove ModelState errors

var viewAddressModel = new Address();
.... // set values
if (!TryValidateModel(viewAddressModel))
{
  if (model.OwnOrRent != "1" || model.OwnOrRent != "9")
  {
    if (ModelState.ContainsKey("HomeValue"))
    {
      ModelState["HomeValue"].Errors.Clear();
    }
    if (ModelState.ContainsKey("PurchasePrice"))
    {
      ModelState["PurchasePrice"].Errors.Clear();
    }
  }
}

You can now use if (ModelState.IsValid) to check if there are any other validation errors and return the appropriate view

Side note: I just used your if condition relating to the OwnOrRent value, but I suspect what you really want is

if (!(model.OwnOrRent == "1" || model.OwnOrRent == "9"))
  • Thank you, I have tried your code, I'm still getting the partial view as the TryValidateModel is still invalid, I can see the errors remove, but as the partial view is returned, so return the error messages. – iggyweb May 19 '15 at 11:49
  • Is there a way of updating the model state and perhaps retrying TryValidateModel after the errors have been removed? – iggyweb May 19 '15 at 11:52
  • Do you mean you are getting an error for property `HomeValue`? Are you actually hitting the `ModelState["HomeValue"].Errors.Clear();` lines? As I noted I think your `if (model.OwnOrRent != "1" || model.OwnOrRent != "9")` is incorrect. –  May 19 '15 at 11:52
  • No you cant use `TryValidateModel` again, that just adds the errors you just removed so its a bit pointless. –  May 19 '15 at 11:53
  • Yes, the code hits the lines you've added and I can see that initially HomeValue has 1 error count, after the code moves on HomeValue has a 0 error count, but as the line `return PartialView("Address", viewAddressModel);' still exists within the TryValidateModel check the partial view renders and so reappears the errors for HomeValue and PurchasePrice. – iggyweb May 19 '15 at 11:56
  • No, the `return PartialView()` needs to be after the `if (!TryValidateModel(viewAddressModel))` block –  May 19 '15 at 11:57
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/78183/discussion-between-iggyweb-and-stephen-muecke). – iggyweb May 19 '15 at 11:58
  • Clearing the errors won't set to true the validation state. The code is good but in my case (in MVC6) I had to add an additional line to set the validation state to valid after clearing errors. Example: `modelState[propertyName].Errors.Clear();` and `modelState[propertyName].ValidationState = ModelValidationState.Valid;` – diegosasw May 03 '16 at 03:41
1

There is a thread about the different options to do conditional validation: ASP.NET MVC Conditional validation

Community
  • 1
  • 1
jobmo
  • 835
  • 1
  • 9
  • 19