假设我有一个界面:
interface IThing {
int Id { get; set; }
string Title { get; set; }
}
在ASP.NET MVC中,我有一个表单发布到这样的控制器动作:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult NewThing([Bind(Exclude = "Id")] SimpleThing thing) {
// code to validate and persist the thing can go here
}
其中 SimpleThing 是一个几乎没有实现 IThing 的具体类。
但是,我希望我的所有方法都能处理界面。我有一个使用NHiberate和它自己的 IThing 实现的数据程序集(我们称之为 RealThing )。我无法将SimpleThing传递给它,因为它会抱怨“未知实体”。
有没有人对更清洁的方法有任何想法?我正在考虑使用工厂类的东西。但是如何让MVC表单绑定器使用呢?
谢谢!
答案 0 :(得分:4)
您可以使用自定义model binders。然而关于msdn的文章完全没用。因此,更好地利用搜索并找到更好的东西。有可用的文章。
答案 1 :(得分:3)
我提出了两种方法。
第一个是将代码添加到我的NHibernate Repository类,将MVC控制器使用的简单POCO类型( SimpleThing )转换为NHibernate想要的实体类型( RealThing ):
/// <summary>
/// A NHibernate generic repository. Provides base of common
/// methods to retrieve and update data.
/// </summary>
/// <typeparam name="T">The base type to expose
/// repository methods for.</typeparam>
/// <typeparam name="K">The concrete type used by NHibernate</typeparam>
public class NHRepositoryBase<T, K>
: IRepository<T>
where T : class
where K : T, new()
{
// repository methods ...
/// <summary>
/// Return T item as a type of K, converting it if necessary
/// </summary>
protected static K GetKnownEntity(T item) {
if (typeof(T) != typeof(K)) {
K knownEntity = new K();
foreach (var prop in typeof(T).GetProperties()) {
object value = prop.GetValue(item, null);
prop.SetValue(knownEntity, value, null);
}
return knownEntity;
} else {
return (K)item;
}
}
因此,存储库中的任何方法都可以调用GetKnownEntity(T item),它会将传入的项的属性复制到NHibernate想要的类型。显然这感觉有点笨重,所以我查看了自定义模型粘合剂。
在第二种方法中,我创建了一个这样的自定义模型绑定器:
public class FactoryModelBinder<T>
: DefaultModelBinder
where T : new()
{
protected override object CreateModel(ControllerContext controllerContext,
ModelBindingContext bindingContext,
Type modelType) {
return new T();
}
}
然后我在Global.asax.cs中注册了:
ModelBinders.Binders.Add(typeof(IThing),
new FactoryModelBinder<RealThing>());
使用如下所示的Controller Action可以正常工作:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult NewThing([Bind(Exclude = "Id")] IThing thing) {
// code to process the thing goes here
}
我喜欢第二种方法,但我的大多数依赖注入内容都在Controller类中。我不想在Global.asax.cs中添加所有这些ModelBinder映射。
答案 2 :(得分:1)
这里有一些很好的建议,我实际上想出了一个有效的解决方案。但是,我最终得到了一些东西。我刚刚创建了特定于我发布的表单数据的模型,并使用了默认的模型绑定器。
更简单,它允许我捕获不属于我的域模型的数据(即像“注释”字段)。
答案 3 :(得分:0)
这不是你想问的问题。
我们使用略有不同的方法来处理您遇到的同样问题。我们的控制器接受逐字段匹配持久实体的DTO。然后我们用AutoMapper来创建将转到数据库的持久实体。这消除了unnessesery接口并锁定了面向公众的API(意味着重命名persistance对象的字段不会破坏我们的客户端代码)。