【问题标题】:One custom model binder to CreateModel and another to BindModel?一个自定义模型绑定器到 CreateModel,另一个到 BindModel?
【发布时间】:2012-02-18 16:03:26
【问题描述】:

背景: 在我的 MVC 回发操作方法中,我接收的是 command 对象而不是视图模型。这个想法是这些命令对象(大致相当于事务脚本)将在进入操作方法时设置并准备好执行,模型绑定器具有在执行过程中使用的设置参数:

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?或者有人知道更好的方法吗?

【问题讨论】:

    标签: asp.net-mvc inversion-of-control model-binding custom-model-binder


    【解决方案1】:

    您可以在原始模型绑定器中使用 GetPropertyValue 方法为 Session 属性提供值:

    public class DependencyModelBinder : DefaultModelBinder
    {
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
            return DependencyResolver.Current.GetService(modelType);
        }
    
        protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
        {
            if (propertyDescriptor.Name == "Session")
            {
                var sessionRepository = DependencyResolver.Current.GetService<ISessionRepository>();
                return sessionRepository.Get(controllerContext.HttpContext.Request["SessionId"]);
            }
            return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-12
      • 1970-01-01
      • 1970-01-01
      • 2016-06-03
      • 1970-01-01
      相关资源
      最近更新 更多