MVC 4 ModelState 无效,因为它试图自动填充值而不接受新值
MVC 4 ModelState invalid because it is trying to auto-fill values and not accept new ones
我有评论区。在视图中只有一个评论编辑框。
@using (Html.BeginForm(new { courseID = @ViewBag.courseID, userName = @User.Identity.Name }))
{
@Html.ValidationSummary(true)
<div class="NewComment">
<div class="editor-field">
@Html.TextAreaFor(model => model.CommentText, new { maxLength = 500})
@Html.ValidationMessageFor(model => model.CommentText)
</div>
<input type="submit" class="PostComment" value="Post Comment" />
<div id="Counter" class="CommentCounter"/>
</div>
}
模型也有评论链接的课程、日期、评论文本和用户。其他值在创建 post 方法中填充。
[HttpPost]
public ActionResult AddComment(CourseComment coursecomment, int courseID, String userName)
{
userName = userName.Split('\')[1];
coursecomment.CommentDate = System.DateTime.Now;
coursecomment.CourseID = courseID;
coursecomment.UserName = db.Users.FirstOrDefault(u => u.UserName == userName).UserID;
if (ModelState.IsValid)
{
db.CourseComments.AddObject(coursecomment);
db.SaveChanges();
}
return RedirectToAction("Details", "Course", new { courseID = courseID });
}
问题出在这里。在我实际完成工作并设置它之前,该模型试图使用 userName
参数作为 courseComment.UserName
的值。设置后 ModelState
不会改变。
例如,domain\abc123
被传递到 post 方法中,并且还在 ModelState
中设置为 UserName
。我做了一些工作,将 userName
更改为 abc123
并找到链接的 ID,假设 ID = 1,给具有上述名称的用户,然后将其插入 courseComment.UserName
ModelState
仍然保留 domain\abc123
并且模型保持无效。
现在,这是原来的工作方式,然后我改变了底层数据库,主要是列名和一些关系。
我的解决方案。
移动从 post 方法接收用户名
[HttpPost]
public ActionResult AddComment(CourseComment coursecomment, int courseID)
{
coursecomment.CommentDate = System.DateTime.Now;
coursecomment.CourseID = courseID;
coursecomment.UserName = db.Users.FirstOrDefault(u => u.UserName == userName).UserID; //Moved
if (ModelState.IsValid)
{
db.CourseComments.AddObject(coursecomment);
db.SaveChanges();
}
return RedirectToAction("Details", "Course", new { courseID = courseID });
}
获取方法。
[HttpGet]
public JsonResult GetUserName(string userName)
{
var ret = db.Users.FirstOrDefault(u => u.UserName == userName).UserID;
return Json(ret, JsonRequestBehavior.AllowGet);
}
然后把视图改成这样
@Html.HiddenFor(model => model.UserName)
....
<script type="text/javascript">
$(function () {
var userName = '@User.Identity.Name.Split('\')[1]';
$.ajax({
url: '@Url.Action("GetUserName", "CourseComment")',
data: { userName: userName },
type: 'get'
}).done(function (data) {
$('#UserName').val(data);
});
});
问题是视图只关心 ModelState
中的内容。这让许多开发者感到困惑,但当你仔细想想时,这是合乎逻辑的。
本质上,ModelState
当然是由 Model
的值组成,但也由 ViewBag
、ViewData
和 [=15= 的值组成],它会覆盖通过 Model
设置的任何内容。要理解原因,请想象这样一种场景:用户正在编辑现有对象,但在其中一个值中出错,导致返回表单以更正错误。如果使用 Model
中的值,则用户的编辑将完全撤消,并替换为对象上的原始值。但是,通过使用来自 Request
的值,ModelState
保留了用户提交的值,允许他们仅进行必要的更正。
总而言之,您必须非常小心地命名请求参数、ViewBag
属性等,与模型中的属性一样。在您的场景中,最简单的解决方案可能是将请求参数 userName
更改为其他内容。
此外,就其价值而言,ModelState
不区分大小写,因此 UserName
与 userName
、username
、USERNAME
或 UsErNaMe
.
我有评论区。在视图中只有一个评论编辑框。
@using (Html.BeginForm(new { courseID = @ViewBag.courseID, userName = @User.Identity.Name }))
{
@Html.ValidationSummary(true)
<div class="NewComment">
<div class="editor-field">
@Html.TextAreaFor(model => model.CommentText, new { maxLength = 500})
@Html.ValidationMessageFor(model => model.CommentText)
</div>
<input type="submit" class="PostComment" value="Post Comment" />
<div id="Counter" class="CommentCounter"/>
</div>
}
模型也有评论链接的课程、日期、评论文本和用户。其他值在创建 post 方法中填充。
[HttpPost]
public ActionResult AddComment(CourseComment coursecomment, int courseID, String userName)
{
userName = userName.Split('\')[1];
coursecomment.CommentDate = System.DateTime.Now;
coursecomment.CourseID = courseID;
coursecomment.UserName = db.Users.FirstOrDefault(u => u.UserName == userName).UserID;
if (ModelState.IsValid)
{
db.CourseComments.AddObject(coursecomment);
db.SaveChanges();
}
return RedirectToAction("Details", "Course", new { courseID = courseID });
}
问题出在这里。在我实际完成工作并设置它之前,该模型试图使用 userName
参数作为 courseComment.UserName
的值。设置后 ModelState
不会改变。
例如,domain\abc123
被传递到 post 方法中,并且还在 ModelState
中设置为 UserName
。我做了一些工作,将 userName
更改为 abc123
并找到链接的 ID,假设 ID = 1,给具有上述名称的用户,然后将其插入 courseComment.UserName
ModelState
仍然保留 domain\abc123
并且模型保持无效。
现在,这是原来的工作方式,然后我改变了底层数据库,主要是列名和一些关系。
我的解决方案。
移动从 post 方法接收用户名
[HttpPost]
public ActionResult AddComment(CourseComment coursecomment, int courseID)
{
coursecomment.CommentDate = System.DateTime.Now;
coursecomment.CourseID = courseID;
coursecomment.UserName = db.Users.FirstOrDefault(u => u.UserName == userName).UserID; //Moved
if (ModelState.IsValid)
{
db.CourseComments.AddObject(coursecomment);
db.SaveChanges();
}
return RedirectToAction("Details", "Course", new { courseID = courseID });
}
获取方法。
[HttpGet]
public JsonResult GetUserName(string userName)
{
var ret = db.Users.FirstOrDefault(u => u.UserName == userName).UserID;
return Json(ret, JsonRequestBehavior.AllowGet);
}
然后把视图改成这样
@Html.HiddenFor(model => model.UserName)
....
<script type="text/javascript">
$(function () {
var userName = '@User.Identity.Name.Split('\')[1]';
$.ajax({
url: '@Url.Action("GetUserName", "CourseComment")',
data: { userName: userName },
type: 'get'
}).done(function (data) {
$('#UserName').val(data);
});
});
问题是视图只关心 ModelState
中的内容。这让许多开发者感到困惑,但当你仔细想想时,这是合乎逻辑的。
本质上,ModelState
当然是由 Model
的值组成,但也由 ViewBag
、ViewData
和 [=15= 的值组成],它会覆盖通过 Model
设置的任何内容。要理解原因,请想象这样一种场景:用户正在编辑现有对象,但在其中一个值中出错,导致返回表单以更正错误。如果使用 Model
中的值,则用户的编辑将完全撤消,并替换为对象上的原始值。但是,通过使用来自 Request
的值,ModelState
保留了用户提交的值,允许他们仅进行必要的更正。
总而言之,您必须非常小心地命名请求参数、ViewBag
属性等,与模型中的属性一样。在您的场景中,最简单的解决方案可能是将请求参数 userName
更改为其他内容。
此外,就其价值而言,ModelState
不区分大小写,因此 UserName
与 userName
、username
、USERNAME
或 UsErNaMe
.