简体   繁体   中英

ASP.NET MVC - How to implement an optional nested model with required fields?

I'm currently in the process of implementing a form in an ASP.NET MVC4 application and I can't seem to find a good and maintainable solution concerning input validation. Given the following (simplified) model:

public class PersonalData
{
    [Required]
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; }

    [Required]
    public AddressData ResidentialAddress { get { return residentialAddress; } }
    private readonly AddressData residentialAddress = new AddressData();

    public AddressData PostalAddress { get; set; }
}

public class AddressData
{
    [Required]
    public string ZipCode { get; set; }

    [Required]
    public string City { get; set; }

    [Required]
    public string Street { get; set; }

    [Required]
    public int HouseNumber { get; set; }
}

I think that this model definition pretty much speaks for itself: I'm capable of declaring properties on the 'PersonalData'-class as 'Required', and I'm also capable of doing the same on the 'AddressData'-model. This approach works with the 'ResidentialAddress'-property, but it gets tricky however with optional nested models, such as the one provided in the 'PostalAddress'-property.

Simply put:

  • All string properties on the ' PersonalData '-model are required;
  • All string properties on the ' AddressData '-object stored in the ' ResidentialAddress '-property are required;
  • ' PostalAddress ' is optional: All string properties on the ' AddressData '-object stored in the ' PostalAddress '-property are required if an ' AddressData '-instance was specified to it.

'Flattening out' the PersonalData-model doesn't seem like a desirable solution to me, especially considering the fact that we're using an EditorTemplate.

What are my options? Am I doing something wrong on a fundamental level? Is there a generally supported technique for this?

I actually found a solution that suits my need! Suppose that a controller has this method:

[HttpPost]
public ActionResult Edit(PersonalData model)
{
    if (ModelState.IsValid)
    {
        // Success
        return Redirect("NextAction");
    }
    return View(model);
}

The instantiation of the ' PersonalData '-object that is used in the 'model'-parameter here is based on the deserialization of the POST-variables that were being sent.

Now, if the following POST-variables were being sent:

  • FirstName : 'John'
  • LastName : 'Doe'
  • ResidentialAddress.ZipCode : '1234AB'
  • ResidentialAddress.City : 'My City'
  • ResidentialAddress.Street : 'My Street'
  • ResidentialAddress.HouseNumber : '123'

Then it will be serialized into a 'PersonalData'-instance, on which the 'ResidentialAddress'-property must be assigned with a valid 'AddressData'-instance. (MVC seems to take care of this automatically).

The presence of 'PostalAddress'-related POST-variables, as follows...

  • PostalAddress.ZipCode : '1234AB'
  • PostalAddress.City : 'My City'
  • PostalAddress.Street : 'My Street'
  • PostalAddress.HouseNumber : '123'

...appears to control whether or not the serialization will result in the instantiation of an 'AddressData'-instance to the 'PostalAddress'-property, which exactly covers the case that I want.

Bottom line: maintain control over what POST-variables are being sent and you should be OK! I hope this helps anyone out; suggestions and/or comments are welcome!

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