I have a controller named UserManagement. It has two methods: AddUser and EditUser.
AddUser and EditUser is very similar except only the user name validation.
This should be the user name description in AddUser operation:
[DisplayName("User Name")]
[Remote("ValidateUserName", "UserMgr", ErrorMessage = "The user name is already existing.")]
[RegularExpression(Verifier.REG_EXP_USER_NAME, ErrorMessage = Verifier.ERRMSG_REG_EXP_USER_NAME)]
public string UserName { get; set; }
And this should be the description in EditUser operation:
In AddUser operation, I use the Remote validation to ensure the user name is not in used in the server side, while that's unnecessary in EditUser operation.
To accomplish that, I created two models, two views. Of course, it works. But it has too many repeated code. It breaks DRY.
If I am using AddUser, I type the right InsertUserName and submit. Then the ModelState.IsValid in the controller will be false, because I did not type the
UpdateUserName,
UpdateUserName is null, it is not needed in the AddUser operation but its validation still takes effect. How to solve this?
For this you will probably need to create a custom [UserNameRequired] validation attribute where you get the value of "IsEditMode" and validate based on that.
Here is an example of how to use validation attributes and also how to get the value of another property.
Anyway, this makes it more complicated than having two ViewModels.
Another solution can be to have a base class which contains common properties, and two derived classes, one for AddUser and the other for EditUser.
Marked as answer by guogangj on May 06, 2012 02:39 AM
guogangj
Member
4 Points
7 Posts
Help, how to avoid repeated code.
May 04, 2012 04:58 AM|LINK
Hi all,
I have a controller named UserManagement. It has two methods: AddUser and EditUser.
AddUser and EditUser is very similar except only the user name validation.
This should be the user name description in AddUser operation:
[DisplayName("User Name")] [Remote("ValidateUserName", "UserMgr", ErrorMessage = "The user name is already existing.")] [RegularExpression(Verifier.REG_EXP_USER_NAME, ErrorMessage = Verifier.ERRMSG_REG_EXP_USER_NAME)] public string UserName { get; set; }And this should be the description in EditUser operation:
[DisplayName("User Name")] [Required(ErrorMessage = Verifier.ERRMSG_REQUIRED)] [RegularExpression(Verifier.REG_EXP_USER_NAME, ErrorMessage = Verifier.ERRMSG_REG_EXP_USER_NAME)] public string UserName { get; set; }In AddUser operation, I use the Remote validation to ensure the user name is not in used in the server side, while that's unnecessary in EditUser operation.
To accomplish that, I created two models, two views. Of course, it works. But it has too many repeated code. It breaks DRY.
How could I do? Any ideas?
Thanks.
gopakumar.r
Participant
959 Points
193 Posts
Re: Help, how to avoid repeated code.
May 04, 2012 05:18 AM|LINK
You can try making your view model of type IValidatableObject and do a custom validaton
public class User: IValidatableObject { [DisplayName("User Name")] public string UserName { get; set; } public IEnumerable<ValidationResult> Validate( ValidationContext context ) { if (Conditions)) { yield return new ValidationResult("Error Message" ); } } }Gopakumar
| Please click “Mark as Answer” on the post(s) if it helps |
abdu292
Participant
1553 Points
371 Posts
Re: Help, how to avoid repeated code.
May 04, 2012 05:24 AM|LINK
Do you think, implementing inheritance will be a solution for your issue?
Please go though the below article to see if it helps you.
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-inheritance-with-the-entity-framework-in-an-asp-net-mvc-application
With best regards,
zuperboy90
Participant
977 Points
819 Posts
Re: Help, how to avoid repeated code.
May 04, 2012 06:27 AM|LINK
Hello
You can also use two UserName properties in the same model.
public string InsertUserName { get; set; }
public string UpdateUserName { get; set; }
guogangj
Member
4 Points
7 Posts
Re: Help, how to avoid repeated code.
May 04, 2012 08:05 AM|LINK
Thanks all.
According to above solutions, I can reduce the repeated code of the models, however, I can not cut down the repeated code of the views still.
Typed view often starts like that:
And... any ideas?
zuperboy90
Participant
977 Points
819 Posts
Re: Help, how to avoid repeated code.
May 04, 2012 08:15 AM|LINK
// ViewModel public class UserViewModel { [DisplayName("User Name")] [Remote("ValidateUserName", "UserMgr", ErrorMessage = "The user name is already existing.")] [RegularExpression(Verifier.REG_EXP_USER_NAME, ErrorMessage = Verifier.ERRMSG_REG_EXP_USER_NAME)] public string InsertUserName { get; set; } [DisplayName("User Name")] [Required(ErrorMessage = Verifier.ERRMSG_REQUIRED)] [RegularExpression(Verifier.REG_EXP_USER_NAME, ErrorMessage = Verifier.ERRMSG_REG_EXP_USER_NAME)] public string UpdateUserName { get; set; } public bool IsEditMode { get { return !string.IsNullOrEmpty(this.UpdateUserName ); } } } // ViewPage @model SystemDemo.Models.UserViewModel @if(Model.IsEditMode) { <div> @Html.TextBoxFor(p => p.UpdateUserName) </div> } else { <div> @Html.TextBoxFor(p => p.InsertUserName) </div> }guogangj
Member
4 Points
7 Posts
Re: Help, how to avoid repeated code.
May 04, 2012 09:01 AM|LINK
Good but still some issues.
If I am using AddUser, I type the right InsertUserName and submit. Then the ModelState.IsValid in the controller will be false, because I did not type the UpdateUserName, UpdateUserName is null, it is not needed in the AddUser operation but its validation still takes effect. How to solve this?
zuperboy90
Participant
977 Points
819 Posts
Re: Help, how to avoid repeated code.
May 04, 2012 09:39 AM|LINK
For this you will probably need to create a custom [UserNameRequired] validation attribute where you get the value of "IsEditMode" and validate based on that.
Here is an example of how to use validation attributes and also how to get the value of another property.
Anyway, this makes it more complicated than having two ViewModels.
Another solution can be to have a base class which contains common properties, and two derived classes, one for AddUser and the other for EditUser.
guogangj
Member
4 Points
7 Posts
Re: Help, how to avoid repeated code.
May 06, 2012 02:43 AM|LINK
Yes, I think it is quite complicated to make a custom validation, but it seems to be the best solution.
BTW, one base class and two derived classes will not be a good method, how can I specified the model type of the view?
zuperboy90
Participant
977 Points
819 Posts
Re: Help, how to avoid repeated code.
May 07, 2012 05:37 AM|LINK
You just pass the derived classes
public class UserPropertiesBaseViewModel { public string Description { get; set; } public string Gender { get; set; } } public class CreateUserViewModel : UserPropertiesViewModel { [DisplayName("User Name")] [Remote("ValidateUserName", "UserMgr", ErrorMessage = "The user name is already existing.")] [RegularExpression(Verifier.REG_EXP_USER_NAME, ErrorMessage = Verifier.ERRMSG_REG_EXP_USER_NAME)] public string UserName { get; set; } } public class EditUserViewModel : UserPropertiesViewModel { [DisplayName("User Name")] [Required(ErrorMessage = Verifier.ERRMSG_REQUIRED)] [RegularExpression(Verifier.REG_EXP_USER_NAME, ErrorMessage = Verifier.ERRMSG_REG_EXP_USER_NAME)] public string UserName { get; set; } } // in views Create.cshtml @model SystemDemo.Models.CreateUserViewModel Edit.cshtml @model SystemDemo.Models.EditUserViewModel