背景: 在我的 MVC 回发操作方法中,我接收的是命令对象而不是视图模型。这个想法是这些命令对象(大致相当于事务脚本)将在进入操作方法时设置并准备好执行,模型绑定器具有在执行过程中使用的设置参数:
public class MyCommand : IMyCommand
{
// In this case Value1 and Value2 are being set by the default model binder from posted form values - wonderful :)
public String Value1 { get; set; }
public String Value2 { get; set; }
public CommandResult ExecuteCommand()
{
// Does something awesome...
}
}
为了让事情变得更复杂一些,我的命令对象具有依赖项(服务、存储库等),这些依赖项在它们各自的构造函数中是必需的;所以我必须创建一个自定义模型绑定器,它使用默认的 DependencyResolver(已经用我的 IoC 容器设置)来构造模型对象:
public class DependencyModelBinder : DefaultModelBinder
{
protected override Object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
return DependencyResolver.Current.GetService(modelType);
}
}
并Global.asax.cs
像这样设置:
ModelBinders.Binders.DefaultBinder = new DependencyModelBinder();
同样,这一切正常,依赖项被注入构造函数,然后默认模型绑定器接管以照常设置属性。
问题: 我遇到的问题是我的所有命令对象都有一个“SessionId”GUID 参数(来自 cookie),他们做的第一件事是尝试使用注入的服务从这个 id 解析会话对象。
public class MyCommand : IMyCommand
{
public MyCommand (ISessionRepository sessionRepository) { ... }
public Guid SessionId { get; set; } // Set by model binder from a cookie...
public CommandResult Execute()
{
Session session = SessionRepository.Get(SessionId);
if (session == null)
// Do something not so awesome...
}
}
我想删除这个重复,所以我创建了第二个模型绑定器,它将负责在存储库中进行此查找,这意味着我的命令对象可以Session
直接具有一个属性(删除会话存储库的构造函数依赖项)。
public class SessionModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var sessionRepository = DependencyResolver.Current.GetService<ISessionRepository>();
return sessionRepository.Get((Guid)controllerContext.HttpContext.Request["SessionId"]);
}
}
我的Global.asax.cs
文件现在看起来像这样:
ModelBinders.Binders.DefaultBinder = new DependencyModelBinder();
ModelBinders.Binders.Add(typeof(Session), new SessionModelBinder());
在单独测试了 SessionModelBinder 之后,我知道它可以工作。但是,当将它与 DependencyModelBinder 结合使用时,它永远不会被调用。如何让 MVC 在构造模型对象时使用我的 DependencyModelBinder,但在绑定会话属性时让它使用我的 SessionModelBinder?或者有人知道更好的方法吗?