1

我有评论区。在视图中只有一个评论编辑框。

@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>

}

该模型也有评论链接的课程、日期、评论文本和用户。其他值在 create 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 方法并在ModelStatefor中设置UserName。我做了一些工作,更改userNameabc123并找到链接的 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);
    });
});
4

1 回答 1

2

问题是所有视图关心的是ModelState. 这让许多开发人员感到困惑,但是当你考虑它时它是合乎逻辑的。

本质上,当然ModelState是由 的值组成Model,但也由 、 和 中的值ViewBag组成ViewDataRequest它们覆盖通过 设置的任何内容Model。为了理解原因,想象一下用户正在编辑现有对象的场景,但其中一个值出错,导致表单被返回以更正他们的错误。如果Model使用了来自的值,则用户编辑将完全撤消,并替换为对象上的原始值。但是,通过使用 中的值RequestModelState保留用户提交的值,只允许他们进行必要的更正。

总而言之,您必须非常小心命名请求参数、ViewBag属性等,与模型上的属性相同。在您的场景中,最简单的解决方案可能是将请求参数更改userName为其他内容。

此外,对于它的价值,ModelState不区分大小写,因此与UserName,userName或相同。usernameUSERNAMEUsErNaMe

于 2015-07-30T17:06:57.687 回答