1

背景: 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...
    }
}

この繰り返しを削除したかったので、リポジトリでこのルックアップを処理する2番目のモデルバインダーを作成しました。つまり、コマンドオブジェクトが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を使用させるにはどうすればよいですか?または、これに対するより良いアプローチを知っている人はいますか?

4

1 に答える 1

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);
    }
}
于 2012-02-19T08:39:58.837 に答える