This question title is likely to be worded poorly so feel free to adjust.
In my MVC application I have a custom attribute which i use to decorate email fields which then either passes or fails the model.
On one pge though I allow the use to submit a comment but I submit via ajax and so do not do a full postback and no model validation.
So I'd like to validate the address but not copy the code. I'd also like to avoid breaking the code out of the validator into yet another class or is this the best wAY?
Is there another way? Can I create the model in the ajax postback and validate it there and then return the partial view with the error messages?
Or is there another way?
You say, ...
So I'd like to validate the address but not copy the code. I'd also like to avoid breaking the code out of the validator into yet another class or is this the best way?
IMO, that is the best way. Factor out the common code. I see your issue though, our EmailValidator inherits from RegularExpressionValidator, so it's hard to factor out. We have a RegEx utility class that uses the same RegEx pattern. We refer to the pattern by constant in both places...
public class EmailAttribute : RegularExpressionAttribute
{
public EmailAttribute() :
base(RegExUtility.SingleEmailAddressPattern)
{
ErrorMessage = "Please enter a valid email address";
}
and
public static class RegExUtility
{
public const SingleEmailAddressPattern = #"...";
public static bool IsValidSingleEmailAddress(string email)
{
return Regex.IsMatch(email, SingleEmailAddressPattern);
For simple Ajax postback actions, I think you can often handle it in the controller or create a separate POCO ViewModel that just supports the Ajax path. I know there are articles on using the same model for both types of actions, but we've found there are usually enough differences that it's worth having separate view models. If they're complex enough, we just factor out the common code.
Related
I am using MVC3 and in certain locations in the code I am using the System.ComponentModel.DataAnnotations.DataType.EmailAddress attribute and letting MVCs Model validation do the validation for me.
However, I would now like to validate an email address in a different section of code where I am not using a model. I would like to use the same method that is already being used by MVC, however I was unable to find any information on how to do so.
EDIT - Sorry if my question was unclear. I will attempt to clarify.
Here is a snippet from the RegisterModel that is included with the default MVC template:
public class RegisterModel
{
...
[Required]
[DataType(DataType.EmailAddress)]
[DisplayName("Email address")]
public string Email { get; set; }
...
}
These attributes instruct mvcs model validation on how to validate this model.
However, I have a string that should contain an email address. I would like to validate the email address the same way that mvc is doing it.
string email = "noone#nowhere.com";
bool isValid = SomeMethodForValidatingTheEmailAddressTheSameWayMVCDoes(email);
As others have said, the DataType attribute doesn't actually do any validation. I would recommend you to look at Data Annotations Extensions which includes already written validation extensions for a variety of things, including Email.
It is also possible to do model validation on your full model explicitly: Manual Validation with Data Annotations.
If you want to do per attribute validation for a specific field/property, you can also look at the tests for DataAnnotationExtensions which should give you what you want:
[TestMethod]
public void IsValidTests()
{
var attribute = new EmailAttribute();
Assert.IsTrue(attribute.IsValid(null)); // Don't check for required
Assert.IsTrue(attribute.IsValid("foo#bar.com"));
..
}
Have a look at this blog post by Scott Guthrie, which shows how to implement validation of an email address using a custom attribute (based on the RegularExpressionAttribute).
You can reuse that logic if you need to validate the email address somewhere else.
You may want to look at this question: Is the DataTypeAttribute validation working in MVC2?
To summarize, [DataType(DataType.EmailAddress)] doesn't actually validate anything, it just says "hey, this property is supposed to be an e-mail address". Methods like Html.DisplayFor() will check for this and render it as foo, but the IsValid() method is pretty much a simple return true;.
You'll have to roll your own code to actually perform validation. The question linked above has some sample code you can use as a starting point.
Just curious on your thoughts or experiences around service layer validation.
I have to process fairly standard validation such as "object with name property doesn't already exist", but I wasn't sure how to return these validation failures back to the controller.
My initial thought was to implement a standard List<ValidationError> but I've seen it done each and every way so was curious the pros/cons of each.
Thanks for any input.
If you go with System.ComponentModel.DataAnnotations entries you can (as you seem to know) decorate your properties with required and many more tags
public class Person
{
[Required(ErrorMessage="object with name property doesn't already exist")]
public string Name { get; set; }
}
although I personally use ViewModels rather than exposing domain mdoels to the view, your controller action can now do something like:
[HttpPost]
public ActionResult SavePerson(Person model)
{
if (ModelState.IsValid)
{
// your model validates - do things
return RedirectToAction("success view here");
}
return View(model);
}
This is one of the standard 'post' handler patterns in MVC. This is the simplest path to getting your object model validating in my opinion.
From there, there are a few other options - your domain object can implement IValidatedableObject and you can yield return the errors (see http://buildstarted.com/2010/09/20/mvc-3s-ivalidatableobject/ as an example).
I'd recommend not mixing the two though, as if you are using dataannotations and have even a single invalid property, the IsValid method on IValidatableObject will not be called.
From there, there's lots you can do with custom validation attributes (the extended version of IsValid seems to give you more flexibility http://msdn.microsoft.com/en-us/library/gg480674%28v=vs.98%29.aspx)
Hope some of the above helps - once you get past the basics there's a lot you can do with it and things like client validation of custom attributes etc. are all fun.
Cheers,
Terry
[edit to add:
After re-reading your post, it may be that you want to only validate at the service layer? If so, I've used the following approach:
public void Setname(string newName)
{
Validator.ValidateProperty(newName, new ValidationContext(this, null, null) { MemberName = "Name" });
Name = newName;
}
obviously your Name property would need a { get; private set; } for this, though you could always add the Validator.ValidateProperty into an extended setter for the public property either.
]
On a new project I'm working on (first time mvc) I've been using the ms code contracts (which throw exceptions) and do all the validation on my domain objects themselves. For things that can't be validated there (such as validations that require database access) I validate in my services and throw exceptions. Additionally like the poster above I have whole separate view models for everything that have data annotations validators on them. The exceptions bubble up and I catch them in the controller and append to the ModelState. There's a lot of overlap with those and the view model validation but it's not much extra effort and allows me to vary the validation per view and yet still have the "core" validations be required.
The book pro asp mvc 2 has another nice way - write a class that inherits Exception and contains a collection of errors. Then you do your validations, add to the collection then throw the exception then he catches it in the controller and copies over to ModelState. This method will let you catch ALL the errors in one exception instead of just one at the service layer.
What's the best way of going about testing model validation without making assumptions on the implementation details of the validation (eg. DataAnnotations).
For example, if I have a Customer model object that has a Firstname property, I want to test that binding a missing value for the Firstname property will result in a validation error but I don't want to test how validation his been implemented. That is, I don't want to use DataAnotations.Validate.
I've seen several, differing, opinions on this floating around and haven't found one that I agree with.
I ended up writing a helper method that wraps ModelValidator and returns IEnumerable<ModelValidationResult>. It requires that MVC be configured with your validation provider of choice, but it means that test code need not change when your validation implementation does:
public static IEnumerable<ModelValidationResult> Validate<TModel>(TModel model)
{
var modelMetadata = ModelMetadata.FromLambdaExpression(r => r,
new ViewDataDictionary<TModel>(model));
ModelValidator validator = ModelValidator.GetModelValidator(
modelMetadata, new ControllerContext());
return validator.Validate(model);
}
This will depend on the framework you are using for validating your models. So what you are asking is not possible without taking this into account. ASP.NET MVC by default uses a data annotations model provider which invokes the validation rules for data annotations and if you want to test this you will need to do a DataAnnotations.Validate in your unit tests or verify that your model is decorated with the proper attributes.
Personally I use FluentValidation.NET which provides an elegant way for unit testing my validators so it is not much of a hassle.
I'm trying to validate user input, in particular user passwords. I have some jQuery validation, but of course I also need to validate on the server side. Now my request comes in to the controller, which will hand it off to a UserService. Everything is loosely coupled, so the controller really doesn't know too much about the inner UserService. Now suppose the user entered a weak password so I need to tell him "hey, that is insufficient."
Question is: What is the best way to do this?
Somehow, I need to be able to call
ModelState.AddModelError(field, exception);
in order to indicate what went wrong, where and why - in the simple example I already know it's the password because it is really the only field on the form, but in general this is not so easy. Now I was close to writing my own Exception type to do something like
ModelState.AddModelError(ex.Field, ex.Message);, where I might need some additional mapping - which is essentiale the path taken in NerdDinner where they have RuleViolations.
However, in NerdDinner, the business object is self-validating. This doesn't seem to be the best way in this case, because the 'business object' here is really just a store for email and password that implements IIdentity. It shouldn't know anything about password lengths and should be reusable across different applications.
Moreover, ArgumentException and ValidationException don't seem to fit either because the first is made for contract violations and the latter is to be used by DataAnnotations.
All this is just the tip of an iceberg of course, because there are so many subtleties lurking around. Perhaps someone can point me in the right direction?
You can use xVal.
If I understand correctly you want to validate whether the user password is sufficient or insufficient. If you aren't using self validation on the object itself then can I suggest you put a validation method on your user service.
...
var result = userService.Validate(newUser);
if (!result.IsValid) {
result.Errors.ForEach( m => ModelState.AddModelError(m.field, m.message));
}
...
How about that?
The only issue with this approach is that to access any validation around the User object you'd have to pass it into the userService, which may or may not be what you want to do.
Answer to comment below:
Well you would have to create a ValidationResult, something like.
public class ValidationResult
{
public string Field {get;set;}
public string Message {get;set;}
}
So if I'm reading correctly, your Controller has a UserService, the UserService has a Validator, and the Validator validate the User.
As you pass this validation up from your Validator to UserService to Controller, just intercept it and use it, then pass it along.
If you don't want to role your own validation library (and you shouldn't) there are some great tools like Enterprise Library and FluentValidation. They can separately define your validation logic external of your objects if that is what you are concerned about.
Here is the lay of the land. Like most people I have my domain object and I have my view models. I love the idea of using view models, as it allows for models to be created specifically for a given view context, without needing to alter my business objects.
The problem I have is with type level validation defined on my domain object and getting those rules to the client. In this case lets say I am using data annotations to describe the validation rules, when I move the data from the domain object to the view model, the view model no longer knows what validation it should get the interface to perform (because the validation is defined back on the domain object).
With MVC 2 you can get it to automatically perform client/server side validation, based on the validation rules of the current object. But because the validation rules are defined on the domain object and not the view model, I would have to duplicate the validation rules on the view model to get this to work.
How do others deal with this type of issue? My thinking is that besides mapping the data from the domain object to the view model, we also need to map across the validation rules, but I haven't really seen others talking about this issue... Brad Wilson has recently talked about this issue at length but hasn't really addressed the duplication of rules on the domain object and on the view models... what are your thoughts?
Cheers
Anthony
The DataAnnotation attributes are about validating input and giving UI feedback to the end user. That's really their only intended use. I use different validation strategies for UI objects and business objects, so the DA validation attributes only end up on models being shown to the user.
This may not be appropriate, but what if you just moved your validation rules/annotations from your Models to your ViewModels? In a few of the projects I've been on, we've chosen to prevent the View from accessing anything but information exposed through its corresponding ViewModel. Since all data interaction would be performed through the ViewModel, there wouldn't be a need to have validation on your Model objects.
The counter to this argument is that you could easily duplicate certain validation rules, since different ViewModels might be interfacing with the same Models. In this case, it might make sense to simply declare your Model as a property exposed on your ViewModel. For postbacks, they could accept a Model as their parameter, allowing the ModelBinder infrastructure to handle the request. In this case, if ModelState.IsValid is false, you could just reassign the property to your ViewModel before redisplaying the View.
I would recommend moving your annotations to your ViewModels. It makes sense since a lot of Views are a) the result of composition of several models or b) a subset of model data.
It turns out that AutoMapper may be able to do this for us automagically, which is the best case scenario.
AutoMapper-users: Transfer validation attributes to the viewmodel?
http://groups.google.com/group/automapper-users/browse_thread/thread/efa1d551e498311c/db4e7f6c93a77302?lnk=gst&q=validation#db4e7f6c93a77302
I haven't got around to trying out the proposed solutions there, but intend to shortly.
(Cross posted this on my (dupe) question as well).
Probably we shouldn't use view models at all?
And define validation rules on model layer entities..
I've been considering this as well for a while now. I totally understand Brad's reply. However, let's assume I want to use another validation framework that is suitable for annotating both domain entities and view models.
The only solution I can come up with on paper that still works with attributes would be to create another attribute that "points" to a domain entity's property that you are mirroring in your view model. Here's an example:
// In UI as a view model.
public class UserRegistration {
[ValidationDependency<Person>(x => x.FirstName)]
public string FirstName { get; set; }
[ValidationDependency<Person>(x => x.LastName)]
public string LastName { get; set; }
[ValidationDependency<Membership>(x => x.Username)]
public string Username { get; set; }
[ValidationDependency<Membership>(x => x.Password)]
public string Password { get; set; }
}
A framework like xVal could possibly be extended to handle this new attribute and run the validation attributes on the dependency class' property, but with your view model's property value. I just haven't had time to flesh this out more.
Any thoughts?