ASP.NET MVC:避免紧耦合结合表单POST时参数
-
22-08-2019 - |
题
让我们说我有这样的接口:
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形式粘结剂使用它?
谢谢!
解决方案 3
有一些好的建议在这里,我确实有一个可行的解决方案上来。不过,我结束了一些完全。我刚刚创建特定的表单数据我张贴的模型和使用默认的模型粘合剂。
更简单,它可以让我捕捉到的数据,是不是我的域模型的一部分(即像“意见”字段)。
其他提示
您可以使用自定义模型粘合剂的。但是MSDN上的文章是完全无用的。所以,最好是采用搜索并找到更好的东西。有可用的物品planaty。
我想出了两种方法来此。
首先是将代码添加到我的NHibernate的存储库类翻译由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项),它会复制项的属性你在传递给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>());
和它正常工作与一个控制器的动作,看起来像这样:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult NewThing([Bind(Exclude = "Id")] IThing thing) {
// code to process the thing goes here
}
我喜欢的第二种方法中,但我的大多数依赖注入的东西是在Controller类。我不喜欢有加在Global.asax.cs中所有这些ModelBinder的映射。
这是不dirrect unswer你的问题。
我们使用略有不同的方法来对付你有同样的问题。我们的控制器接受由字段相匹配的持久化实体字段的DTO。然后,我们的用户 AutoMapper 创建persisten实体会到数据库中。这消除unnessesery接口和锁定了面向公众的API(意味着重命名持久性对象的字段不会破坏我们的客户端代码)。