Html.HiddenFor偶尔无法使用模型信息进行设置

3

我们在MVC3中使用Html.HiddenFor时偶尔出现绑定不正确的问题。我们无法复现它,但是我们在日志中看到了nullrefs,并且这让我们非常困扰。

我们有以下的模型和控制器结构:

public class DummyController
{
    [HttpGet]
    public ActionResult ReturnAPage(int NumericID)
    {
        //NumericID should never be 0 or negative, but let's check to make sure
        if (NumericID < 1)
        {
            return RedirectToAction("TracyJordanStabbingRobot");
        }
        return View("DummyView", new DummyViewModel(NumericID));
    }

    [HttpPost]
    public ActionResult TakePageSubmission(DummyViewModel model)
    {
        //AnObject relies on having a non-zero ID
        ComplexObject AnObject = new ComplexObject(model.NumericID);
        AnObject.UseMe();
    }
}

public class DummyViewModel
{

     public DummyViewModel() {}
     public DummyViewModel(int ID)
     {
         NumericID = ID;
     }

     public int NumericID { get; set; }
}

...和以下视图结构:

DummyView.cshtml

@model DummyViewModel
<html>
    <head></head>
    <body>
        <p>THIS IS A VIEW!</p>
        <form id="DummyViewForm" action="/RouteTo/TakePageSubmission" method="post">
            @Html.Partial("_PartialDummyView", Model)
            <input type="submit" value="Submit This!" />
        </form>
    </body>
</html>

_PartialDummyView.cshtml

@model DummyViewModel
   <p>Heard you like views...</p>
   @Html.HiddenFor(model => model.NumericID)

考虑到我们在初始控制器操作中检查小于零的值,因此可以推断出@Html.HiddenFor(model => model.NumericID)永远不应该具有小于零的值。
话虽如此,当我们在TakePageSubmission操作中使用AnObject时,会出现空引用错误。
当我们深入记录model.NumericID值时,我们发现它以零的形式传递,这是不可能的,因为只有使用非零值才能访问DummyView。
我们有点困惑,因为我们无法可靠地重现此问题,所以我们没有任何办法知道可能导致这种情况的原因。有人遇到过类似的情况吗?
编辑:我们正在对表单提交进行ModelState验证,但我们没有检查通过的NumericID是否为0。当我们检查时,模型无效,这证明HiddenFor被设置不正确。此外,页面的路由实际上包括NumericID,例如,我们看到了这种情况的发生:
http://our.site.com/RouteToReturnAPage/1736/
...其中操作的参数明显已设置,模型已正确构建,但由于某种未知原因,HiddenFor NumericID值为0。这真的很令人困惑。

你是否只是在 RedirectToAction("TracyJordanStabbingRobot"); 前面漏了一个 return - Forty-Two
1
@Liam 不,一切都在我们网站的控制范围内。 - antinescience
@Liam,除了这是伪代码而不是实际片段之外,它与我们在生产中所做的工作是一对一的。就像你说的那样,这本来是不可能的,但却发生了。 - antinescience
1
@Liam 那可能就是原因了。如果没有 HttpPost,我可以直接转到 http://../Dummy/TakePageSubmission 并完全绕过表单提交。 - Erik Philips
2
抱歉一直在编辑 - 实际上在生产中它被标记为仅限POST。 - antinescience
显示剩余7条评论
2个回答

3
您的默认 0 值绑定是从 MVC View 到相同页面的 post 后,认为由于 post 过程中出现错误而重新加载了相同的视图。正确的绑定将在对不同操作调用的 load/action 调用上发生。
有一个 hack 解决方法,即在重新加载视图之前使用 ModelState.Clear();
此外,完全不使用 Helpers 来创建隐藏字段,可以使用以下内容:
<input type="hidden" value="@Model.NumericID" id="NumericID" name="NumericID" />

Reference: http://blogs.msdn.com/b/simonince/archive/2010/05/05/asp-net-mvc-s-html-helpers-render-the-wrong-value.aspx


0

首先,在您的模型中缺少默认构造函数。如果没有它,应用程序绑定时会抛出异常。

您可以通过在客户端编辑隐藏字段来重现错误。因此,用户可以将ID更改为0或任何其他值。如果您没有在分布式环境上运行应用程序,则可以使用TempData在操作之间传递ID。这样,您就可以防止数据篡改。

TempData["NumericID"] = NumericID;

抱歉,就像我说的,我匆忙地输入了代码。有一个默认构造函数。 - antinescience

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接