Asp.net mvc ModelState对于ASP.NET MVC 2中模型的私有属性报告为无效
我正在使用ASP.NET MVC 2.0,我正在尝试利用控制器中的模型绑定和modelstate验证。然而,我遇到了一个问题,我想和大家分享一下,看看你们的想法 好的,我的模型类库中有我的干净用户pocoAsp.net mvc ModelState对于ASP.NET MVC 2中模型的私有属性报告为无效,asp.net-mvc,architecture,modelbinders,modelstate,Asp.net Mvc,Architecture,Modelbinders,Modelstate,我正在使用ASP.NET MVC 2.0,我正在尝试利用控制器中的模型绑定和modelstate验证。然而,我遇到了一个问题,我想和大家分享一下,看看你们的想法 好的,我的模型类库中有我的干净用户poco namespace Model { public partial class User { public virtual int Id { get; private set; } public virtual string UserNam
namespace Model
{
public partial class User
{
public virtual int Id { get; private set; }
public virtual string UserName { get; private set; }
public virtual string DisplayName { get; set; }
public virtual string Email { get; set; }
public User(string displayName, string userName)
: this()
{
DisplayName = displayName;
UserName = userName;
}
}
}
我选择的设计只允许在构建对象后编辑某些属性。例如,用户名只能在构建对象时设置,对我来说这是OO意义上的,但却是我问题的关键,所以我想在这里强调一下
然后我有一个“buddy类”,它为我的用户类定义验证元数据
namespace Model
{
[MetadataType(typeof(UserMetadata))]
public partial class User
{
class UserMetadata
{
[Required]
public virtual int Id { get; set; }
[Required]
public virtual string UserName { get; set; }
[Required]
public virtual string DisplayName { get; set; }
[RegularExpression(@"^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$", ErrorMessage = "Invalid address")]
public virtual string Email { get; set; }
}
}
}
然后在我的web层中,我希望允许我的用户能够编辑此对象。因此,在我的profile controller中有以下两种操作方法
namespace Web.Controllers
{
public class ProfileController : Controller
{
[Authorize]
public ActionResult Edit()
{
var user = _session.Single<User>(x => x.UserName == HttpContext.User.Identity.Name );
return View(user);
}
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize]
[TransactionFilter]
public ActionResult Edit(User updatedUser)
{
// Get the current user to update.
var user = _session.Single<User>(x => x.UserName == HttpContext.User.Identity.Name);
if (ModelState.IsValid)
{
TryUpdateModel(user);
// Update store...
}
return View(updatedUser);
}
}
}
名称空间Web.Controllers
{
公共类ProfileController:控制器
{
[授权]
公共行动结果编辑()
{
var user=\u session.Single(x=>x.UserName==HttpContext.user.Identity.Name);
返回视图(用户);
}
[HttpPost]
[ValidateAntiForgeryToken]
[授权]
[交易过滤器]
公共操作结果编辑(用户更新用户)
{
//获取要更新的当前用户。
var user=\u session.Single(x=>x.UserName==HttpContext.user.Identity.Name);
if(ModelState.IsValid)
{
TryUpdateModel(用户);
//更新存储。。。
}
返回视图(updateUser);
}
}
}
这有一个强类型的视图来配合它
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Model.User>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Edit
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<%=Html.Script("jquery.validate.js")%>
<%=Html.Script("MicrosoftMvcJQueryValidation.js")%>
<%=Html.Script("MvcFoolproofJQueryValidation.js")%>
<div class="container">
<div class="column span-14">
<% using (Html.BeginForm()) {%>
<%= Html.AntiForgeryToken() %>
<fieldset>
<%: Html.DisplayFor(model => model.UserName) %>
<%= Html.Label("Display Name") %>
<%= Html.HiddenFor(model => model.DisplayName)%>
<%= Html.ValidationMessageFor(model => model.DisplayName)%>
<%= Html.Label("Email address") %>
<%= Html.EditorFor(model => model.Email)%>
<%= Html.ValidationMessageFor(model => model.Email)%>
<%= Html.HiddenFor(model => model.UserName)%>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
</div>
<div class="clear"></div>
<% } %>
</div>
</asp:Content>
使用模型视图
这对我来说就是不干?!如果没有合适的现有模型对象(例如,我使用注册模型视图),我很乐意使用这些
CustomModelBinder
我的首选,但我不确定我知道我在做什么!!如果我能让活页夹只绑定到它可以设置的属性,那么我会笑
人们怎么想?对以上选项的评论,任何其他解决方案,我的架构是否偏离了标准
谢谢:)“我设计为不设置它,因此,通过设计,我不希望模型绑定器设置它,但我不希望出现验证错误。我认为它只会对可以设置的属性产生验证错误。”
请在此处阅读有关此设计决策的更多信息:
有趣的是,大多数人的抱怨与你的抱怨完全相反
你基本上是告诉系统,不能设置的东西应该总是设置好。所以我不会说MVC工作不正常或诸如此类。你只是在编写一个不可能的场景
总的来说,您刚刚达到metadatabuddy技术的痛点。主要是需要对新场景和编辑场景进行不同的验证
“如果我这样做,我会允许自己更改现有用户的用户名。我必须在某个地方添加额外的逻辑来捕捉这一点,这不是很好。我还必须在操作方法上添加一个绑定排除,以阻止任何淘气的人试图通过帖子设置它。”
我不知道你对这些代码更改吃得多饱。您将向单个方法调用添加一个简单字符串。有什么大不了的?我在这里采用务实的方法。“我设计为不设置它,因此,通过设计,我不希望模型绑定器设置它,但我不希望出现验证错误。我认为它只会对可以设置的属性产生验证错误。”
请在此处阅读有关此设计决策的更多信息:
有趣的是,大多数人的抱怨与你的抱怨完全相反
你基本上是告诉系统,不能设置的东西应该总是设置好。所以我不会说MVC工作不正常或诸如此类。你只是在编写一个不可能的场景
总的来说,您刚刚达到metadatabuddy技术的痛点。主要是需要对新场景和编辑场景进行不同的验证
“如果我这样做,我会允许自己更改现有用户的用户名。我必须在某个地方添加额外的逻辑来捕捉这一点,这不是很好。我还必须在操作方法上添加一个绑定排除,以阻止任何淘气的人试图通过帖子设置它。”
我不知道你对这些代码更改吃得多饱。您将向单个方法调用添加一个简单字符串。有什么大不了的?我会采取务实的方法。我会使用视图模型,因为它最适合这份工作。不要认为DRY意味着不能在两个对象上重复属性,可以认为它是“不要在两个地方重复逻辑或保存相同的数据”。在这种情况下,处理模型绑定的语义与您的域模型不匹配,因此您需要一种方法来转换它。我会使用视图模型,因为它最适合此工作。不要认为DRY意味着不能在两个对象上重复属性,可以认为它是“不要在两个地方重复逻辑或保存相同的数据”。在这种情况下,处理模型绑定的语义与您的域模型不匹配,因此您需要一种方法来翻译它。jfar发布了一个不错的链接,指向Brad Wilson的一篇文章,其中Brad评论
您仍然可以进行部分编辑,但是
您不能进行任何部分验证
更多所以如果你排除绑定
带有[必需]的东西
属性,则验证将失败。
你有几个选择要解决
这:
- 使用准确镜像表单数据的视图模型
- 调用前,用数据预先填写[必填]但未绑定的字段
(尝试)更新模型,以便
瓦利达