我正在使用nhibernate& MVC3。 我有两个简单的模型和一个视图模型,它包含了它自己的一些属性+每个模型的一个属性。
e.g。
class Contact() { ... }
class Address() { ... }
class EditContactVM() {
public string something {get;set;}
public Contact contact {get;set;}
public Address address {get;set;}
}
所有基础模型都实现了一个接口(IMyModel),它具有Id属性和一些其他位。
我有一个通用模型绑定器,它从视图发回的数据中提取Id,并从数据库中获取对象:
public class NHibernateModelBinder<T> : DefaultModelBinder where T: IMyModel
{
private DataAccessService DataAccessService { get; set; }
public NHibernateModelBinder(DataAccessService dataAccessService)
{
DataAccessService = dataAccessService;
}
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ValueProviderResult IdResult = bindingContext.ValueProvider.GetValue("Id");
IAgBiTechModel model = null;
if (IdResult != null)
{
model = DataAccessService.Get<T>(Convert.ToInt32(IdResult.AttemptedValue));
}
return model;
}
}
和模型绑定程序提供程序,为该类型创建适当的绑定程序。
这一切都很完美,我最终在我的控制器中使用一个EditContactVM对象填充了从数据库中适当填充的属性。
然而,有一件事令我困惑: 根据我的理解,在模型绑定器完成它并从数据库中获取实体之后,应该使用从视图中发回的值来更新对象的属性。
e.g。我正在编辑与Id 5的联系。 联系人姓名在视图中从“James”更新为“Tom”。 在回发后,模型绑定器将从数据库中获取联系人5并将其分配给EditContactVM.Contact。 ---现在我希望MVC用我视图中的数据更新EditContactVM.Contact。即当我到达我的控制器时,EditContactVM.Contact.Name将是'Tom'。 相反,我只是获取未修改的数据库对象并丢失视图发回的数据。
我认为唯一可能与之相关的是EditContactVMBinder看起来像这样:
public class ContactVMBinder : DefaultModelBinder
{
private Func<ContactVM> EmptyViewModelFactory { get; set; }
public ContactVMBinder(Func<ContactVM> emptyViewModelFactory)
{
EmptyViewModelFactory = emptyViewModelFactory;
}
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
bindingContext.ModelMetadata.Model = EmptyViewModelFactory();
return base.BindModel(controllerContext, bindingContext);
}
}
编辑:添加了一些视图标记
@using (Html.BeginForm("Edit", "Contact", FormMethod.Post)) {
<div class="row">
@Html.ValidationSummary(true)
</div>
@Html.HiddenFor(m => m.contact.Id)
@Html.HiddenFor(m => m.contact.Timestamp)
if (Model.address != null && Model.address.Id > 0)
{
@Html.HiddenFor(m => m.address.Id);
@Html.HiddenFor(m => m.address.Timestamp)
}
<div class="row">
<h4>Contact Details</h4>
</div>
<div class="editor-label row">
@Html.LabelFor(m => m.contact.FirstName)
</div>
<div class="editor-field row">
@Html.TextBoxFor(m => m.contact.FirstName)
<span style="margin: 2">
@Html.ValidationMessageFor(m => m.contact.FirstName)
</span>
</div>
}
答案 0 :(得分:1)
通过重写BindModel,您实际上是在告诉框架不要做“它的事情”并且您将自己绑定模型。您必须为框架调用super.BindModel()以将视图中的数据绑定到它为您创建的实例。另一种方法是覆盖OnModelUpdated(),在那个阶段框架创建了你的模型实例并用视图中的数据填充它(调用super.BindModel后可以在BindModel中获得相同的结果),然后你可以用你想要从数据库中检索的任何内容更新该实例。