Is there a way to implement the idea of a data domains (at a property level) inside of a class that is used as a model in a view in ASP.Net MVC 4?
Consider this code:
public class LoginProfileModel {
[DisplayName("Login ID")]
[Required(ErrorMessage = "Login ID is required.")]
public string LogonID { get; set; }
[DisplayName("Password")]
[Required(ErrorMessage = "Password cannot be blank.")]
[StringLength(20, MinimumLength = 3)]
[DataType(DataType.Password)]
public string Password { get; set; }
}
Here is a LoginProfileModel in for ASP.Net MVC 4. It uses a variety of metadata/data annotations so that I can create a clean view with this code:
@model myWebSite.Areas.People.Models.LoginProfileModel
@using ( Html.BeginForm( "Index" , "Login" ) ) {
@Html.ValidationSummary()
@Html.EditorForModel()
<input type="submit" value="Login" />
}
I use the idea of a "Login ID" and a "Password" in more than one view, and therefore, in more than one view model. I want to be able to define the attributes that a Password uses, or possibly the Password itself with all of it's data annotations in a single location so that I can reuse all those definitions where needed, rather than respecifying them every time they are used:
[DisplayName("Password")]
[Required(ErrorMessage = "Password cannot be blank.")]
[StringLength(20, MinimumLength = 3)]
[DataType(DataType.Password)]
public string Password { get; set; }
Is that possible some way?
You can do this using a buddy class, which provides metadata for your view model. Like so:
Then your view models:
Note the use of
partial
in the class definitions. This is what allows this approach to work. One caveat, other than the obvious problem with DRY, is that I believe the metadata class has to reside in the same namespace as your view models, else it complains. Other than that, this should do what you want.The following attributes affect the validation process of your View.
For the Validation attributes, you can create a class like this:
You can use it as follows:
The other two attributes that you mentioned are Directly derived from the
Attribute
class, and I don't think there's a way to consolidate them into a single attribute.I'll update you with an edit soon.
So now we're left with:
EDIT:
According to this post: Composite Attribute, it's not possible to merge attributes.
As a corollary to John H's answer, you could just use inheritance and make those view models that have the "idea of a LogonId and password" inherit from that base view model. This would solve the MetaData issues that were mentioned in the previous answer.
Now in the SomeOtherClassThatNeedsLoginInfo, those properties and their related DataAnnotations will be available to you.
Another idea would be just to pass that LoginInfo as a property on your other view models.