Strad
Strad

Reputation: 36

ASP:NET MVC 4 dynamic validation of a property depending of the current value of another property

I have a problem finding out a way to validate dynamically a property depending of the current value of another property in the same model. I have searched a lot and was not able to find an answer or similar example.

In my model I have a zip code property and a countryID property. In the DB for each different country I have a different regex to validate the zip code. Then with the countryID I can get from the DB the apropiate regex to validate the zip code of the corresponding country

So in my model, depending on the value of the current countryID I want to have the validation of the zip field.

I tried creating a custom validation attribute "ZipValidation(countryID)", but in the model it doesn't let me have the value of another property as a parameter:

public class AddressViewModel
{
    ...
    [Display(Name = "Country ID")]
    public Guid? countryID { get; set; }

    [Required]
    //[ZipValidation(countryID)] does not compile because of the countryID
    [Display(Name = "Zip")]
    public string zip { get; set; }

}

Any idea how this can be achieved?

Upvotes: 0

Views: 1986

Answers (3)

Strad
Strad

Reputation: 36

I've resolved it finally with the [Remote] validation attribute as Jonesy suggested, and with Json and Ajax in my controller. It is something like that:

public class AddressViewChannelModel
{
    ....
    [Display(Name = "CountryID")]
    public Guid? countryID  { get; set; }

    [Required]
    [Remote("ValidateZipCode", "Address", AdditionalFields = "countryID")]
    [Display(Name = "Zip")]
    public string zip { get; set; }
}

public class AddressController : Controller
{
  ...
    public JsonResult ValidateZipCode(string zip, string countryID)
    {
        ValidationRequest request = new ValidationRequest();
        request.CountryID = Guid.Parse(countryID);
        request.Zip = zip;

        ValidationResponse response = new ValidationResponse();
        response = _addressApi.ZipValidation(request);

        if(response.IsSuccessful == false)
        {
            return Json("Not a valid zip code for your chosen country!"),  JsonRequestBehavior.AllowGet);
        }
        else
        {
            return Json(true, JsonRequestBehavior.AllowGet);
        }
    }
}

Upvotes: 1

Chris Pratt
Chris Pratt

Reputation: 239260

It's a little low-tech and you probably should investigate using validation attributes if you have the time and inclination, but for completeness, this is a workable solution. In your post action:

[HttpPost]
public ActionResult MyAwesomePostAction(AddressViewModel model)
{
    if (!ValidationUtil.IsValidZipCode(model.zip, model.countryID))
    {
        ModelState.AddModelError("zip", "Not a valid zip code for your chosen country.");
    }

    if (ModelState.IsValid)
    {
        ...
    }

    return View(model);
}

I assumed some library where you would store the validation outside of the controller. That way, there's not a lot of extraneous code here in your action, and if you need to do this again, you don't have to repeat the validation logic.

Upvotes: 0

astian
astian

Reputation: 684

What you need to do here is to create your own validation attribute... In the constructor of the attribute, as Rodrigo said, you will pass the Name of the property that your validation attribute will also use, in your case countryID. Then you will use reflection to take the value of that property and knowing that you can do your validation. This will all be well, and even with a little luck and a lot of skill you can make it reusable, however if you want client validation you need to implement it by yourself. It is a long story and I see you have been given appropriate references from where to understand the entire process, so I will finish with giving you the one I learned from: Flexible Conditional Validation with ASP.NET MVC

Upvotes: 0

Related Questions