6
public class City
{
   [DynamicReqularExpressionAttribute(PatternProperty = "RegEx")]
   public string Zip {get; set;}
   public string RegEx { get; set;} 
}

I woud like to create this attribute where the pattern come from an other property and not declare static like in the original RegularExpressionAttribute.

Any ideas would be appreciated - Thanks

2 Answers2

7

Something among the lines should fit the bill:

public class DynamicRegularExpressionAttribute : ValidationAttribute
{
    public string PatternProperty { get; set; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        PropertyInfo property = validationContext.ObjectType.GetProperty(PatternProperty);
        if (property == null)
        {
            return new ValidationResult(string.Format("{0} is unknown property", PatternProperty));
        }
        var pattern = property.GetValue(validationContext.ObjectInstance, null) as string;
        if (string.IsNullOrEmpty(pattern))
        {
            return new ValidationResult(string.Format("{0} must be a valid string regex", PatternProperty));
        }

        var str = value as string;
        if (string.IsNullOrEmpty(str))
        {
            // We consider that an empty string is valid for this property
            // Decorate with [Required] if this is not the case
            return null;
        }

        var match = Regex.Match(str, pattern);
        if (!match.Success)
        {
            return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
        }

        return null;
    }
}

and then:

Model:

public class City
{
    [DynamicRegularExpression(PatternProperty = "RegEx")]
    public string Zip { get; set; }
    public string RegEx { get; set; }
}

Controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var city = new City
        {
            RegEx = "[0-9]{5}"
        };
        return View(city);
    }

    [HttpPost]
    public ActionResult Index(City city)
    {
        return View(city);
    }
}

View:

@model City
@using (Html.BeginForm())
{
    @Html.HiddenFor(x => x.RegEx)

    @Html.LabelFor(x => x.Zip)
    @Html.EditorFor(x => x.Zip)
    @Html.ValidationMessageFor(x => x.Zip)

    <input type="submit" value="OK" />
}
Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Hi Darin great solution but it do not work on client side unobtrustiv validation Philipp – Philipp Troxler May 26 '11 at 13:10
  • 1
    @Philipp Troxler, that's normal. I didn't implement it as client side validation was not part of your question. To achieve this you could make this attribute implement `IClientValidatable` and register a custom jQuery adapter. Here's an example that might put you on the right track: http://stackoverflow.com/questions/4784943/asp-net-mvc-3-client-side-validation-with-parameters/4784986#4784986 – Darin Dimitrov May 26 '11 at 14:10
  • Greate, atleast I am not getting that EntityValidationException, I am getting some hopes now :) What I am getting is PropertyInfo property = validationContext.ObjectType.GetProperty(PatternProperty); returning null, so now Exception is "MyExpression" is unknown property. Spent 2 days already to find this, could you please help me out? Thanks :) – SMI Jan 23 '14 at 05:29
0

override the Validate method that takes the ValidationContext as a parameter, use the ValidationContext to get the regex string from the related property and apply the regex, returning the matched value.

Xhalent
  • 3,914
  • 22
  • 21