Asp.net mvc Razor不会在HiddenFor中渲染隐藏的精确PK

Asp.net mvc Razor不会在HiddenFor中渲染隐藏的精确PK,asp.net-mvc,entity-framework,asp.net-mvc-4,razor,Asp.net Mvc,Entity Framework,Asp.net Mvc 4,Razor,在我的ASP MVC 4站点中遇到了一个奇怪的问题。如果用户打开create表单并尝试向数据库中添加代理,我们自然会首先对字段进行验证。如果出现错误,我们将代理保存为未完成状态,并将用户重定向回创建页面 当用户试图重新保存代理时,会出现此错误。在第一次回发时,代理保存到数据库中并生成PK。但是,在第二次回发时,PK被发送到服务器,其值为0,而不是刚刚自动生成的值 我在Create视图中添加了一个HiddenFor,但是每次都会显示一个0值 我还详细介绍了代码,以确保在调用.Save后生成PK,调

在我的ASP MVC 4站点中遇到了一个奇怪的问题。如果用户打开
create
表单并尝试向数据库中添加代理,我们自然会首先对字段进行验证。如果出现错误,我们将代理保存为未完成状态,并将用户重定向回创建页面

当用户试图重新保存代理时,会出现此错误。在第一次回发时,代理保存到数据库中并生成PK。但是,在第二次回发时,PK被发送到服务器,其值为
0
,而不是刚刚自动生成的值

我在
Create
视图中添加了一个
HiddenFor
,但是每次都会显示一个
0

我还详细介绍了代码,以确保在调用
.Save
后生成PK,调用
返回视图时PK仍然存在,并确保在渲染视图时
Model.ID
属性包含相同的值

不管怎样,如果我右键单击页面并查看源代码,隐藏字段的呈现方式如下:

<input data-val="false" data-val-number="The field ID must be a number." data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="0" />
查看

@model MonetModelFromDb.Models.AgentTransmission

@{
    ViewBag.Title = "Create new Agent";
}

@Html.HiddenFor(model => model.CreatedDate, new { data_val = "false" })
@Html.HiddenFor(model => model.CreatedOperator, new { data_val = "false" })
@Html.HiddenFor(model => model.ReferenceNumber, new { data_val = "false" })
@Html.HiddenFor(model => model.Region, new { data_val = "false" })
@Html.HiddenFor(model => model.INDDist, new { data_val = "false" })
@Html.HiddenFor(model => model.LastChangeDate, new { data_val = "false" })
@Html.HiddenFor(model => model.LastChangeOperator, new { data_val = "false" })
@Html.HiddenFor(model => model.EditTaxId, new { data_val = "false" })
@Html.HiddenFor(model => model.ParentId, new { data_val = "false" })
@Html.HiddenFor(model => model.IsSubstat, new { data_val = "false" })
@Html.HiddenFor(model => model.ID, new { data_val = "false" })
为节渲染隐藏

<input data-val="false" data-val-date="The field CreatedDate must be a date." id="CreatedDate" name="CreatedDate" type="hidden" value="" />
<input data-val="false" id="CreatedOperator" name="CreatedOperator" type="hidden" value="" />
<input data-val="false" id="Region" name="Region" type="hidden" value="NM-834" />
<input data-val="false" id="INDDist" name="INDDist" type="hidden" value="834" />
<input data-val="false" data-val-date="The field LastChangeDate must be a date." data-val-required="The LastChangeDate field is required." id="LastChangeDate" name="LastChangeDate" type="hidden" value="4/8/2015 10:43:30 AM" />
<input data-val="false" id="LastChangeOperator" name="LastChangeOperator" type="hidden" value="TYPCLS" />
<input data-val="false" data-val-required="The EditTaxId field is required." id="EditTaxId" name="EditTaxId" type="hidden" value="False" />
<input data-val="false" data-val-number="The field ParentId must be a number." id="ParentId" name="ParentId" type="hidden" value="" />
<input data-val="false" data-val-required="The IsSubstat field is required." id="IsSubstat" name="IsSubstat" type="hidden" value="False" />
<input data-val="false" data-val-number="The field ID must be a number." data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="0" />
编辑

如果我删除
HiddenFor
helper并简单地剪切/粘贴呈现的
input
标记,我就能够捕获正确的PK值。然而,这是一个有点黑客,所以我希望找到一个更优雅的解决方案(如果可能的话)


这里经常会问到关于这个问题的各种问题。基本上,它归结为
ModelState
对象及其值覆盖视图的实际模型上的值这一事实。发布表单时,
ID
属性的
ModelState
对象中设置了
0
。在post操作中,保存实体,这会导致其
ID
属性更新,但
0
仍处于
ModelState
状态。返回视图时,
0
再次设置为
ID
的值,因为这也是
ModelState
中的内容

它以这种方式工作的原因最好通过一个例子来解释。假设您有一个表单,其中您正在编辑一个现有实体,该实体有一个设置为“Foo”的
Name
属性。用户在表单中将其更改为“Bar”,然后发布表单。但是,他们忽略了填写必填字段,因此错误会阻止保存他们的更新。此时该怎么办?如果我们使用模型值,
Name
字段将重置为“Foo”。但是,如果使用了
ModelState
,则
Name
字段将保留用户对“Bar”的修改。在后一种情况下,他们只是修复错误并再次发布。在前者中,他们必须重新制作之前对表单所做的所有更改,这显然是一种非常糟糕的用户体验

现在,关于如何解决这个问题。最好的方法是遵循PRG模式(Post-Redirect-Get)。如果提交良好,并且您成功保存了更改,则不要返回视图,即使您希望用户能够立即进行其他更改。如果需要,只需重定向回相同的操作,但重定向过程足以清除
ModelState
,这样用户现在就可以与从数据库中新提取的更新模型进行交互

如果这不可行,那么只需清除
ModelState
。我建议不要完全清除它,因为您可能会导致一些非常真实的用户失望,如上面的示例所述。如果确实无法执行重定向,请尝试仅清除确实需要的
ModelState
中的值

ModelState.Remove("ID");

我记得在过去遇到过类似的奇怪情况,结果是直接渲染字段而不是使用辅助对象。如果你打开视图,它是否显示正确的id?是的,它显示正确的id,但是我希望找到一个更优雅的解决方案。。。如果可能的话。我尝试了几种不同的方法,但在这些情况下都没有成功。一直都是这样。希望其他人会有一个更优雅的解决方案
    [HttpPost]
    [MonetAuthorize]
    public ActionResult Create(AgentTransmission agenttransmission, bool andAddAgent = false)
    {
    .
    .
    .
        //Determine if this is first POST or not
        if (agenttransmission.ID > 0)
        {
            db.Entry(agenttransmission).State = EntityState.Modified;
        }
        else
        {
            db.AgentTransmission.Add(agenttransmission);
        }
        db.SaveChanges();

        //Send back to view if errors pressent
        if (!String.IsNullOrWhiteSpace(errorMsg))
        {
            return View(agenttransmission);
        }           
    }
<input data-val="false" id="ID" name="ID" type="hidden" value="@Model.ID" />
ModelState.Remove("ID");