[英]Partial Model Validation in MVC4
我有一个PartialView
,它是一个用于创建或修改用户并实现ViewModel DynamicActionUserModel
的表单。 引用此partialView的视图显示了所有MembershipUsers
的表,并且能够创建新用户Membership.CreateUser()
或修改用户'Membership.UpdateUser()`。 partialView中的表单向我的控制器发送ajax帖子以提交数据。
我遇到的问题是,当用户创建其userName,电子邮件, 密码和角色作为DynamicActionUserModel.RegisterModel
被序列化回控制器并进行验证,但是当用户被修改时,密码不是可用的属性(我也不想让它在客户端修改)因此没有在DynamicActionUserModel.RegisterModel
和ModelState.IsValid
设置它总是false。
也许我的模型和视图的设计需要改变,或者有没有办法验证模型但是在修改用户时忽略密码? 不确定这个最佳做法是什么。
我想另一个选择是创建另一个ViewModel和另一个专门用于修改用户的partialView,但这似乎很草率。
模型
public class DynamicActionUserModel {
public string Action { get; set; }
public RegisterModel RegisterModel { get; set; }
}
public class RegisterModel {
[Required]
[Display(Name = "User Name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
public string[] SelectedRoles { get; set; }
public MultiSelectList Roles { get; set; }
}
调节器
[HttpGet]
public ActionResult CreateUser() {
var model = new DynamicActionUserModel {
Action = "CreateUser",
RegisterModel = new RegisterModel {
Roles = new MultiSelectList(System.Web.Security.Roles.GetAllRoles())
}
};
return PartialView("_UserPartial", model);
}
[HttpGet]
public ActionResult ModifyUser() {
var model = new DynamicActionUserModel {
Action = "ModifyUser",
RegisterModel = new RegisterModel {
Roles = new MultiSelectList(System.Web.Security.Roles.GetAllRoles())
}
};
return PartialView("_UserPartial", model);
}
[HttpPost]
public ActionResult ModifyUser(DynamicActionUserModel model) {
bool isEqual = true;
if(!ModelState.IsValid) { // this is always false because password is empty
return PartialView("_UserPartial", model);
}
var user = Membership.GetUser(model.RegisterModel.UserName);
// do stuff
Membership.UpdateUser(user);
return Json(new {success = false});
}
视图
@using RobotDog.Models
@model IEnumerable<RobotDog.Models.UserModel>
<!-- table of users -->
<div class="modify-form">
@Html.Action("ModifyUser")
</div>
<div class="create-user-form">
@Html.Action("CreateUser")
</div>
PartialView
@model RobotDog.Models.DynamicActionUserModel
@using(Html.BeginForm(Model.Action,"Admin", FormMethod.Post, new { @class = "ajax" })) {
<!-- Email -->
@Html.TextBoxFor(x => x.RegisterModel.Email, new { @class = inputSize, placeholder = "Email"})
<!-- UserName -->
@if(Model.Action == "ModifyUser") {
@Html.HiddenFor(x => x.RegisterModel.UserName)
<span class="input-xlarge uneditable-input">@Html.DisplayNameFor(x => x.RegisterModel.UserName)</span>
} else {
@Html.TextBoxFor(x => x.RegisterModel.UserName, new { @class = inputSize, placeholder = "User Name" })
}
<!-- Password -->
@if(Model.Action == "Createuser") {
@Html.PasswordFor(x => x.RegisterModel.Password, new { @class = inputSize, placeholder = "Password"})
}
<!-- Roles -->
@Html.ListBoxFor(x => x.RegisterModel.SelectedRoles, Model.RegisterModel.Roles)
<!-- Submit -->
<input type="submit" value="Submit" class="btn"/>
}
在调用ModelState.IsValid
之前尝试使用ModelState.Remove("password")
,但是如果不总是需要属性, 这里建议您不要将其标记为必需。
注意:即使在MVC4中,文档也是向后的,应该说:
确定是否存在与指定键关联或前缀的任何ModelError对象。
我为此做了一个小的扩展方法助手:
public static class ModelStateHelpers
{
public static bool IsValidFor<TModel, TProperty>(this TModel model,
System.Linq.Expressions.Expression<Func<TModel, TProperty>> expression,
ModelStateDictionary modelState)
{
string name = ExpressionHelper.GetExpressionText(expression);
return modelState.IsValidField(name);
}
}
用法很简单:
bool billingValid = model.IsValidFor(x => x.CheckoutModel.BillingAddress, ModelState);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.