0

次のルートを想定します。

{region}/{storehouse}/{controller}/{action}

これらの 2 つのパラメーターregionstorehouse全体で、単一のエンティティー a を識別しますStorehouse。したがって、いくつかの倉庫のコンテキストで一連のコントローラーが呼び出されています。そして、次のようなアクションを書きたいと思います:

public ActionResult SomeAction(Storehouse storehouse, ...)

ここであなたの考えを読むことができます:「カスタムモデルバインダーを書いてください、男」。そうです。ただし、質問は

カスタム モデル バインダー内で魔法の文字列を回避するにはどうすればよいですか?
これが私の現在のコードです:

public class StorehouseModelBinder : IModelBinder
{
    readonly IStorehouseRepository repository;
    public StorehouseModelBinder(IStorehouseRepository repository)
    {
        this.repository = repository;
    }

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var region = bindingContext.ValueProvider.GetValue("region").AttemptedValue;
        var storehouse = bindingContext.ValueProvider.GetValue("storehouse").AttemptedValue;
        return repository.GetByKey(region, storehouse);
    }
}

単一のキーがあれば、bindingContext.ModelName使用できます...
おそらく、すべてのアクションにオブジェクトを提供する別の方法がありStorehouseます。つまり、コントローラーのプロパティとして宣言し、Controller.Initialize.

4

1 に答える 1

0

私は別のアプローチに行き着きました。モデル バインディングは、私の目的には適切なメカニズムではありません。アクション フィルターが最適です。

名前は質問と同じではありませんが、Site を Storehouse として扱います。

public class ProvideCurrentSiteFilter: IActionFilter
{
    readonly ISiteContext siteContext;

    public ProvideCurrentSiteFilter(ISiteContext siteContext)
    {
        this.siteContext = siteContext;
    }

    void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)
    {
    }

    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.ActionParameters["currentSite"] = siteContext.CurrentSite;
    }
}

ISiteContextHttpContext.Current実現は、サイト リポジトリからオブジェクトを分析してプルします。使用HttpContext.Currentはエレガントすぎません、同意します。ただし、すべてが IoC を通過するため、テスト容易性は損なわれません。

ProvideCurrentSiteAttributeを使用するという名前のアクション フィルタ属性がありますProvideCurrentSiteFilter。したがって、私のアクション メソッドは次のようになります。

[ProvideCurrentSite]
public ActionResult Menu(Site currentSite)
{
}
于 2010-04-02T08:37:49.443 に答える