MVC不会通过提交表单返回Readonly Properties

时间:2013-02-02 11:54:18

标签: asp.net-mvc form-submit readonly antiforgerytoken

我已经有一段时间试着搞清楚这一点! 一般来说:我希望从我的表格中获得“只读,隐藏”属性。

我从示例中修剪了所有的不确定性:
我有以下模型

public class ChangeOrderDetailModel
{
...
...
    [ReadOnly(true)]
    public int OrderId { get; set; }
}

并在视图中:

@using (Html.BeginForm("SubmitChangeOrder", "Order"))
{
    @Html.AntiForgeryToken()<br/>
    @Html.HiddenFor(o => o.OrderId) <br />
...
...
}

现在:

  1. 在View HTML中,OrderID有一个隐藏字段...

  2. 我不希望任何人更改“OrderID”,因为它可能会导致安全问题。

  3. 我需要提交表单中的OrderID号码

  4. 问题将表单提交给Controller时 OrderController.SubmitChangeOrder(ChangeOrderDetailModel mdl){}
    我发现mdl.OrderID 总是= 0

  5. 当我从属性中删除ReadOnly(true)属性时,一切正常,但任何人都可以使用简单的JS更改字段的值,这很糟糕。
    而且我不想只在哈希标记上进行中继,因为它也很容易被破坏:(

  6. 为什么这样工作?
    我错过了什么,更好的方式来实现我喜欢的东西?

    注意:可能会有多个变更单并行进行,因此会话有点问题。

    感谢所有人。

1 个答案:

答案 0 :(得分:1)

通过使用[Readonly(true)],您明确指示模型绑定器不将字段绑定到模型的属性。通过使用Html.HiddenFor渲染属性已经在渲染的html中实现了您想要的效果。您可以在控制器操作中包含第二个参数int OrderId,模型绑定器将值绑定到该变量

流氓用户仍然可以编辑OrderId。防止此类操作的一种方法是加密OrderId并在模型中使用加密值,然后在页面上使用。然后,一旦发生回发,您将解密加密的OrderId。加密和解密可以封装在模型本身中

@TomerW,如果我正确理解你的问题,你的核心问题是流氓用户可以在客户端更改OrderId的值,我的建议不是以裸体形式呈现OrderId,而是在服务器上对其进行加密使用仅在服务器上已知的密钥。您应该将HTML中的加密值呈现为隐藏字段。流氓用户可能仍会尝试更改相关值,但解密将失败,您将知道有人试图捏造您的价值。以下是存根实现,

public class ChangeOrderDetailModel
{
    [ReadOnly(true)] /*You are instructing the model binder not to bind this value*/
    public int OrderId { get; set; }

    private string _OrderIdEnc;
    public string OrderIdEnc
    {
        /*Encryp*/
        get
        {
            return Encrypt(OrderId);
        }

        set
        {
            _OrderIdEnc = value;
        }
    }

    public void DecryptPayload()
    {
        /* Decrypt, and this will fail is someone has edited the value */
        OrderId = Decrypt(_OrderIdEnc);
    }
}

在视图模型中,使用@Html.HiddenFor(o => o. OrderIdEnc)。您可以使用标准窗口加密来进行加密和解密。

为了极其安全,您可以为每个请求/响应会话使用不同的密钥。这将阻止更高级的流氓用户用旧版本替换OrderIdEnc。

我确信可能还有其他解决方案,但上面是我多次使用并且已经使用的模式

干杯