【问题标题】:ASP.Net MVC strongly typed partial views and inherited propertiesASP.Net MVC 强类型分部视图和继承属性
【发布时间】:2012-01-31 20:34:44
【问题描述】:

我正在使用 MS MVC 3 构建一个 Web 应用程序并遇到了一个问题,这可能是由于我对模型绑定的理解存在漏洞。

首先,我有一个相当标准的模型(为简洁起见省略了无关的内容,更改了名称以保护无辜对象的隐私):

public class ModelBase
{
    public int Id { get; set; }
}

 public class Order : ModelBase
{
    public List<Product> Products { get; set; }
}

public class Product : ModelBase
{
    public int OrderId { get; set;}
}

为了显示和编辑这些,我有一个对 Order 类进行强类型化的视图,其中包含一个对 Product 类进行强类型化的部分视图。部分视图的顶部如下所示:

@model Product

@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.Id)
@Html.HiddenFor(model => model.OrderId)
//loads of actual editable properties

我像这样将部分插入到主视图中:

@Html.Partial("EditorTemplates/Product", Model.Products.First())

...当视图在浏览器中呈现时,“Id”隐藏输入包含订单的 ID,而不是我期望和需要的产品 ID :(

我错过了什么?可以在不改变模型和视图结构的情况下修复吗?

【问题讨论】:

  • 看起来没问题,你怎么确定Id是订单? OrderId 显示是否正确?
  • OrderId 确实显示正确,并且与 Id 字段中显示的值相同。不过,我想我不确定它是否来自 Order 的值,因为该值也作为请求 url 的一部分存在(/Orders/Step2/10,其中 10 是 Order Id)。会不会是这个值覆盖了 Id 字段?
  • 可以通过DB确认orderid和这条记录的id是否相同?
  • 在我的特定测试用例中,订单 ID 为 10,产品 ID 为 3。我在这两个字段中都得到 10。没有 ID 为 10 的产品。

标签: asp.net-mvc model-view-controller inheritance properties partial


【解决方案1】:

在更改我的测试项目时,我可以确认

/Home/Index?id=33

/Home/Index/33

确实会覆盖模型值。你能把这个参数从url中去掉吗?

【讨论】:

  • 就是这样! binder 以不区分大小写的方式将路由值放入字段中,并覆盖模型中的值。我在 Global.Asax 中为应用程序的订单编辑部分添加了一条新路由,如下所示:"Orders/{StepNo}/{OrderId}" ...现在我的值被保留,因为它不再将默认路由值 {id} 与我的“Id”匹配场地。所需要的只是我的操作参数的新路线和一些新名称。不需要进行结构更改,而且 MVC 不会像我最初担心的那样存在继承问题。非常感谢您的帮助:)
【解决方案2】:

你必须改变结构。

您可以将部分内容放到主视图中,或者将部分内容强输入到 Order 而不是 Product,或者使用 Html.Hidden() 构造隐藏字段。 MVC 并未将 HiddenFor 中项目的整个路径相对于您的 post 操作中的模型。

即。在 html 中你会看到

<input type="hidden" name="Id" />

但你真的想要

<input type="hidden" name="Products[0].Id" />

为了区分字段和项目。


当您尝试使用相同的名称发布两个不同的隐藏输入时,上述问题仍然存在,但是我还编写了一个可以在客户端工作的测试项目。

希望这会有所帮助:

控制器

public ActionResult Index()
        {
            Order order = new Order() { Id = 1 };
            order.Products = new List<Product>() { new Product() { Id = 3, OrderId = 1 } };
            return View("Order",order);
        }

型号

public class Order : IdentityBase
    {
        public List<Product> Products { get; set; }
    }

    public class Product : IdentityBase
    {
        public int OrderId { get; set; }
    }

 public class IdentityBase
    {
        public int Id { get; set; }
    }

查看

@model MvcApplication1.Models.Order

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>Order</title>
</head>
<body>
    <div>
        @Html.HiddenFor(model => model.Id)
        @foreach (MvcApplication1.Models.Product product in Model.Products)
        {
            <div class="product">
                @Html.Partial("Product", product)
            </div>
        }
    </div>
</body>
</html>

局部视图

@model MvcApplication1.Models.Product

@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.Id)
@Html.HiddenFor(model => model.OrderId)

客户端 HTML

<!DOCTYPE html> 
<html>
<head>    
    <title>Order</title>    
</head>    
<body>    
    <div>    
       <input id="Id" name="Id" type="hidden" value="1" />    
       <div class="product"> 
                <input id="Id" name="Id" type="hidden" value="3" />    
                <input id="OrderId" name="OrderId" type="hidden" value="1" />    
       </div>
    </div>
</body>

【讨论】:

  • 这里是我们获得这种洞察力的地方:hanselman.com/blog/…
  • 我了解如何为集合构造控件,但这不是我想做的。这只是我要编辑的第一个元素。正如您可能从部分路径中看出的那样,我希望在整个应用程序中重用产品编辑部分。尝试使用 @Html.Hidden("Id", Model.Id) 会产生与 HiddenFor 相同(错误)的结果。但是,执行@Html.Hidden("P_Id", Model.Id) 会给出预期值,因此很明显正确的值存在于部分视图中,但只是在某些时候被覆盖。
  • 您的 Html 表单的范围是什么?您是否有可能发回两个名为“Id”的元素?您可以在页面的 html 或 POST 操作中的表单值集合中检查这一点。
  • 我还没有发布 POST。客户端收到 GET 请求的响应后,该值是错误的。如果我将“Id”字段的名称更改为其他名称,我能够向客户端输出正确的值,但如果我不这样做,则在组合过程中的某个时间点似乎会覆盖该值风景。错误模型的 ID,订单,被添加到部分字段中,或者请求 url 中的 ID 以某种方式进入我的字段,我不确定。
  • 谢谢,这是有道理的。 HiddenFor 命名约定不知道局部视图的深度,我们也遇到过类似的问题。我认为我们在 HiddenFor(m=>m.Parent[m.Parent.IndexOf(m)].Id) 或类似的东西上取得了一些成功,但我必须敲一个测试项目来检查
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-06
  • 2010-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多