ASP.NET MVC 2 RC模型与NHibernate和下拉列表绑定

ASP.NET MVC 2 RC模型与NHibernate和下拉列表绑定,nhibernate,asp.net-mvc-2,drop-down-menu,updatemodel,modelbinder,Nhibernate,Asp.net Mvc 2,Drop Down Menu,Updatemodel,Modelbinder,在使用NHibernate进行数据访问的ASP.NET MVC 2 RC应用程序中,我遇到了模型绑定问题。我们正在尝试以RubyonRails的方式构建应用程序,并且有一个非常简单的体系结构,其中域实体从数据库一直使用到视图 应用程序有两个域实体,可以通过以下两个类来说明: public class Product { ... public Category Category { get; set; } } public class Category {

在使用NHibernate进行数据访问的ASP.NET MVC 2 RC应用程序中,我遇到了模型绑定问题。我们正在尝试以RubyonRails的方式构建应用程序,并且有一个非常简单的体系结构,其中域实体从数据库一直使用到视图

应用程序有两个域实体,可以通过以下两个类来说明:

public class Product {
    ...

    public Category Category { get; set; }      
}

public class Category {
    public int Id { get; set; }
    public string Name { get; set; }
}
在呈现编辑表单的视图中,有以下语句显示下拉列表:

<%= Html.DropDownListFor(model => model.Category.Id, 
       new SelectList(ViewData["categories"] as IList<Category>, "Id", "Name"), 
       "-- Select Category --" ) %>
我的问题是product.Category.Id设置为表单中选择的值,例如Category.Id=“2”。使用默认模型绑定器会导致以下类型的NHibernate异常:

identifier of an instance of Name.Space.Entities.Category was altered from 4 to 2
这很有意义,因为产品已经分配了一个类别,并且只有该现有类别的主键正在更改。应指定另一个类别实例


我想可以创建一个定制的ModelBinder来处理这个问题,但是有没有更简单的方法来解决这个问题呢?可以(也应该)修改域实体来处理这个问题吗?

我以前对Linq to SQL类使用过类似的技术,没有任何问题。我认为您不需要为此定制ModelBinder。UpdateModel应该更新传递给它的产品类,而不是附加到它的Category子类。检查DropDownListFor帮助程序生成的html。元素的名称是什么?它应该是Products表中外键字段的名称(例如,“CategoryID”或“Product.CategoryID”而不是“Category.Id”)。如果是“Category.Id”-请尝试将DropDownListFor的第一个参数更改为“model=>model.Category”或“model=>model.CategoryID”(或任何外键字段)。这将导致UpdateModel只更新Product类中的外键字段,而不更新Category类ID。

我们当时选择的解决方案与此类似:

TryUpdateModel(product, null, null, new[] {"Category"}, collection);
int categoryId;
if (int.TryParse(collection["Category.Id"], NumberStyles.Integer, CultureInfo.InvariantCulture, out categoryId) && categoryId > 0) {
    product.Category = _categoryRepository.Load(categoryId);
}
else {
    product.Category = null;
}

我们只是告诉模型绑定器排除关联属性并手动处理。不漂亮,但在当时工作….

我通过更改以下行解决了编辑页面上组合框的类似问题

@Html.DropDownListFor(x => x.Employee.Id, new SelectList(ViewBag.Employees, "Id", "DisplayName"))


所以我按照布莱恩的建议删除了“.Id”。更改前,模型仅包含员工Id,更改后,活页夹还将员工的所有详细信息加载到模型中。

外键不可用,因为关系完全由NHibernate处理。我只是手动处理分类案例,而没有创建自定义模型绑定器。您找到了解决此问题的方法吗?我遇到了完全相同的问题。不,我从来没有找到一个好的解决方案(但是,我们没有花很多时间寻找它)。我们在活页夹之外明确地处理了这个问题。你能给我一些提示吗?你实际上是如何在活页夹之外处理这个问题的。你根本就没有使用TryUpdateModel/UpdateModel吗?那是很久以前的事了,但我认为通过使用TryUpdateModel,但排除关联,然后手动更新该属性afterwords,你很快就解决了这个问题。我添加了一个简单的答案,说明了我们的做法
@Html.DropDownListFor(x => x.Employee.Id, new SelectList(ViewBag.Employees, "Id", "DisplayName"))
@Html.DropDownListFor(x => x.Employee, new SelectList(ViewBag.Employees, "Id", "DisplayName"))