ASP.NET MVC 传递数据

4
大家好,我正在尝试使用ASP.NET MVC和Entity Framework。我想知道在控制器和视图之间传递数据的最佳方法是什么,然后再将其传回。我稍作解释:
我有一个用于创建新“Receipt”对象的动作。
        [Authorize]
    public ActionResult CreateReceipt(int id)
    {
           //I create the receipt object
            Receipt newReceipt = new Receipt();
           // assign some information about the owner of the receipt 
           // and the group that it belongs to
            newReceipt.Group = group;
            newReceipt.Owner = user;
            //send off to the view to be displayed
            return View(newReceipt);
    }

所以,我基本上创建了一个收据并预先填写了一些信息(包括授权用户和一些组ID信息)。然后,我可以将其发送到带有各种表单元素的视图中,让用户填写其他缺失的字段并提交以添加新的收据。如果所有来自收据对象的字段都在表单上显示,则这一切都运行得很好。
如果我删除用户不应该触及的东西的表单元素(例如组号、收据所属的用户ID等...),那么当我提交表单并在控制器中接收时:
        [HttpPost]
    [Authorize]
    public ActionResult CreateReceipt(Receipt receipt)
    {

        if (ModelState.IsValid)
        {
            using (EntityFrameworkEntities context = new EntityFrameworkEntities)
            {
                context.AddToReceipts(receipt);
                context.SaveChanges();
            }
            return RedirectToAction("Index");
        }

        return View(receipt);
    }

然后,我填写并发送到视图中的所有有用的预加载信息都不会随着提交一起返回。我知道我可以将UserID或GroupID放入隐藏字段中,然后它会随着POST一起返回,但那感觉很不对。从技术上讲,有人可以进去更改隐藏值并重新提交POST。我可能需要检查以确保所有内容都应该在它们应该存在的位置,但这似乎又要再次访问数据库来获取我已经得到的信息。

如果有人能够详细说明一下从模型到视图到控制器传递数据的标准方法,那就太好了。感谢您的时间和帮助!

2个回答

5

如果您担心有人会通过更改隐藏字段的值来影响其他记录,可以在隐藏字段中填充ID值并加密,然后在回传时进行解密。


1
+1,这是主要答案,我在答案周围添加了更多内容以便更加直接地帮助。 - Chris Marisic
这似乎是一个很好的解决方案,可以真正防止篡改等问题。我提问的原因更多是因为看起来我不应该在表单中添加隐藏字段,但又要保留发送到视图的值以进行往返。我可能错了,但我想这就是发布问题的目的 :-) 我一定会研究这个解决方案。谢谢您的信息! - Justin Rassier
如果你想完全避免在页面中使用id字段,你仍然需要设计其他方式将id传递给客户端,以便在postback时传回。这是无法避免的。 - Dave Swersky
1
是的,它必须存在于视图中的某个地方,否则模型绑定时ID将为null。哎呀! - Chev
1
作为曾经的WebForms开发人员并且使用WebForms和ViewState工作,我总是感到在页面上使用隐藏字段很不舒服,这似乎是一种Hack方法。但是在做越来越多的MVC项目后,我发现在页面上使用隐藏字段是如何让互联网正常运行的。 - Chris Marisic

3

我最近为我的一个现有应用程序添加了类似的功能。这将扩展@Dave Swersky的答案。

假设一个业务对象为

Receipt
ID
Cost
ShippingAddress

我需要一个ViewModel

ReceiptViewModel
ID
Cost
CostHash
ShippingAddress

您的视图可能会有以下内容:

Html.HiddenFor(m => m.Id)
Html.HiddenFor(m => m.CostHash)
Html.LabelFor(m => m.Cost)
Html.LabelFor(m => m.ShippingAddress)

对于业务对象到视图模型的映射,除了成本哈希(CostHash)之外,一切都很简单。您需要计算Cost + 私钥 + 可预测的盐值(例如收据ID)的Sha256哈希(或其他哈希)。您想要包括对象的ID或其他已知值的变量的原因是为了防止系统用户绕过哈希。

如果您只使用原始值+私钥,则对于每次$10的成本输出结果将相同。这将允许人们轻松地从不同的收据中转置成本值和成本哈希值,但是如果您添加ID作为盐的一部分,则Receipt 1的$10的哈希与Receipt 2的$10的哈希将不同。如果您需要保护同一对象上的许多类似值,并且仍然担心用户可能会将成本和成本哈希值移动到其他行项目中,则需要添加更多内容到盐中,例如该项的属性名称等。

当视图模型发送回控制器时,您需要计算成本的预期哈希并将其与CostHash属性进行比较,以验证它们是否相等。如果它们不同,则意味着有人试图篡改。


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