0

I have tried using EmailAddressAttribute on a parameter posted to a controller but it doesn't have the same effect as if it was used within a model.

This is my code:

    public void AddEmail(int id, [EmailAddress]string emailAddress)
    {
        if (!ModelState.IsValid)
            throw new Exception();
    }

The emailAddress parameter is within the ModelState but it's always valid. However, if I use it within a model like below then it works perfectly fine.

    public class TestModel
    {
        public int Id { get; set; }
        [EmailAddress]
        public string EmailAddress { get; set; }
    }

    public void AddEmail(TestModel model)
    {
        if (!ModelState.IsValid)
            throw new Exception();
    }

The EmailAddressAttribute class has the AttributeTargets.Parameter so I thought it would work the same.

Can anyone confirm if this is just the way it is? Or is there a way to get it to work the same as the model does?

EDIT: I am using .NET Framework 4.6.2.

Thanks

Murphybro2
  • 2,207
  • 1
  • 22
  • 36

1 Answers1

0

I don't know if you can use DataTypeAttributes as parameters in a function. But as an easy way to just check if it is a valid email notation you could use this code:

try {
    var addr = new System.Net.Mail.MailAddress(email);
    return addr.Address == email;
}
catch {
    return false;
}

EDIT 1:

As mentioned from Mark Vincze here on his blog, you could create a new ActionFilterAttribute like this when you want to have attributes in your action parameters.

public class ValidateActionParametersAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var descriptor = context.ActionDescriptor as ControllerActionDescriptor;

        if (descriptor != null)
        {
            var parameters = descriptor.MethodInfo.GetParameters();

            foreach (var parameter in parameters)
            {
                var argument = context.ActionArguments[parameter.Name];

                EvaluateValidationAttributes(parameter, argument, context.ModelState);
            }
        }

        base.OnActionExecuting(context);
    }

    private void EvaluateValidationAttributes(ParameterInfo parameter, object argument, ModelStateDictionary modelState)
    {
        var validationAttributes = parameter.CustomAttributes;

        foreach (var attributeData in validationAttributes)
        {
            var attributeInstance = CustomAttributeExtensions.GetCustomAttribute(parameter, attributeData.AttributeType);

            var validationAttribute = attributeInstance as ValidationAttribute;

            if (validationAttribute != null)
            {
                var isValid = validationAttribute.IsValid(argument);
                if (!isValid)
                {
                    modelState.AddModelError(parameter.Name, validationAttribute.FormatErrorMessage(parameter.Name));
                }
            }
        }
    }
}

But this also just workes for Actions. Because the ModelState-Class was created to make it easier to check if an incoming binding is valid or not and not just to validate random objects. Here is more about that.

So in your case when AddEmail is a 'normal' method and not an Action you should not use this. In this case, use another validation method such as my first answer.

And if you want to read even more about validation, take a look at this blog post from Brad Wilson.

bene_rawr
  • 119
  • 1
  • 10