Model Required value for only given scenario when form is submitted

时光毁灭记忆、已成空白 提交于 2021-01-28 19:29:59

问题


I have a registration page that asks for your given Country and State. This is all fine and dandy when you are from a Country that has states like in the U.S, but when you are from a country that doesn't have states I would like to leave the state field blank and still allow you to register and submit the page still.

In my DB table for Country I have a column set boolean true if they have states and false if they don't. This way when someone selects a country with states it loads the states in the drop down menu.

I have the model set up like such.

      [Required(ErrorMessage = "State is required.")]                
      public string StateId { get; set; }

I tried to make the value nullable but that seem to have no effect. So Is it even possible to do validation like this using DataAnnotations?


回答1:


As r3plica said, you could create a custom validation method to check the state. In the custom validation method, you could query the database and check whether the country has state and then return the validation result. Code as below:

public class DeveloperViewModel
{
    public int Id { get; set; }
    [Required(ErrorMessage = "Name is Required")]
    public string Name { get; set; }
    [Required(ErrorMessage ="Country is Required")]
    public string Country { get; set; }
    [RequiredIfHasState("Country", ErrorMessage ="State is Required")]
    public string State { get; set; }
}

public class RequiredIfHasStateAttribute : ValidationAttribute
{
    private readonly string _comparisonProperty;

    public RequiredIfHasStateAttribute(string comparisonProperty)
    {
        _comparisonProperty = comparisonProperty;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        ErrorMessage = ErrorMessageString;

        //get entered state value
        var stateValue = (string)value;
        var property = validationContext.ObjectType.GetProperty(_comparisonProperty);
        if (property == null)
            throw new ArgumentException("Property with this name not found");
        //get the country value
        var countryValue = (string)property.GetValue(validationContext.ObjectInstance);
        //get the current dbcontext
        var _context = (MvcMovieContext)validationContext.GetService(typeof(MvcMovieContext));
        //query the database and check whether the country has state.
        if (_context.Countries.Where(c => c.CountryCode == countryValue).Select(c => c).FirstOrDefault().HasState)
        {
            if(stateValue == null)
            { 
                //if country has state and the state is null. return error message
                return new ValidationResult(ErrorMessage);
            }
            else
            {
                //if country has state and the state is not found.
                if(!_context.Countries.Where(c => c.CountryCode == countryValue).Any(c => c.States.Any(e => e.StateName == stateValue)))
                {
                    return new ValidationResult("State not found");
                }
            }
        }   
        return ValidationResult.Success;
    }
}

The screenshot as below (GB country doesn't contain state, the US country has states):




回答2:


This question is very similar to this:

Custom Validation Attributes: Comparing two properties in the same model

Basically, you create a custom data attribute. In your case (pseudo code)

public class MyViewModel
{
    [RequiredIfHasState("End", ErrorMessage = "State is required.")]
    public string StateId { get; set; }

    public bool HasState { get; set; }
}

public class RequiredIfHasStateAttribute : ValidationAttribute
{
    private readonly string _comparisonProperty;

    public RequiredIfHasStateAttribute(string comparisonProperty)
    {
        _comparisonProperty = comparisonProperty;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        ErrorMessage = ErrorMessageString;
        var currentValue = (bool)value;

        var property = validationContext.ObjectType.GetProperty(_comparisonProperty);

        if (property == null)
            throw new ArgumentException("Property with this name not found");

        var comparisonValue = (string)property.GetValue(validationContext.ObjectInstance);

        if (currentValue && string.IsNullOrEmpty(comparisonValue))
            return new ValidationResult(ErrorMessage);

        return ValidationResult.Success;
    }
}


来源:https://stackoverflow.com/questions/63909558/model-required-value-for-only-given-scenario-when-form-is-submitted

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!