views:

81

answers:

1

Hi guys/gals,

Could someone help me with this issue. I'm trying to figure out how to check two values on a form, one of the two items has to be filled in. How do I do a check to ensure one or both of the items have been entered?

I'm using viewmodels in ASP.NET MVC 2.

Here's a little snip of code:

The view:

Email: <%=Html.TextBoxFor(x => x.Email)%>
Telephone: <%=Html.TextBoxFor(x => x.TelephoneNumber)%>

The viewmodel:

    [Email(ErrorMessage = "Please Enter a Valid Email Address")]
    public string Email { get; set; }

    [DisplayName("Telephone Number")]
    public string TelephoneNumber { get; set; }

I want either of these details to be provided.

Thanks for any pointers.

+2  A: 

You can probably do this in much the same way as the PropertiesMustMatch attribute that comes as part of the File->New->ASP.NET MVC 2 Web Application.

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class EitherOrAttribute : ValidationAttribute
{
    private const string _defaultErrorMessage = "Either '{0}' or '{1}' must have a value.";
    private readonly object _typeId = new object();

    public EitherOrAttribute(string primaryProperty, string secondaryProperty)
        : base(_defaultErrorMessage)
    {
        PrimaryProperty = primaryProperty;
        SecondaryProperty = secondaryProperty;
    }

    public string PrimaryProperty { get; private set; }
    public string SecondaryProperty { get; private set; }

    public override object TypeId
    {
        get
        {
            return _typeId;
        }
    }

    public override string FormatErrorMessage(string name)
    {
        return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
            PrimaryProperty, SecondaryProperty);
    }

    public override bool IsValid(object value)
    {
        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
        object primaryValue = properties.Find(PrimaryProperty, true /* ignoreCase */).GetValue(value);
        object secondaryValue = properties.Find(SecondaryProperty, true /* ignoreCase */).GetValue(value);
        return primaryValue != null || secondaryValue != null;
    }
}

The key part of this function is the IsValid function that determines if one of the two parameters has a value.

Unlike normal Property-based attributes, this is applied to the class level and can be used like so:

[EitherOr("Email", "TelephoneNumber")]
public class ExampleViewModel
{
    [Email(ErrorMessage = "Please Enter a Valid Email Address")]
    public string Email { get; set; }

    [DisplayName("Telephone Number")]
    public string TelephoneNumber { get; set; }
}

You should be able to add as many as these as you need per form, but if you want to force them to enter a value into one of more than two boxes (Email, Telephone or Fax for example), then you would probably be best changing the input to be more an array of values and parse it that way.

Amadiere
Thanks Amadiere!
beebul