2016-12-10 12 views
0

私はasp.net MVC Webアプリケーションを持っています。これは、ユーザーがそれらのいくつかをピックアップして詳細を表示することができるいくつかのエンティティのリストです。モデルバインダーのフィリングエンティティとバインダーを置換する外部メソッドの比較

このアプリケーションのほとんどの動作には、パラメータとしてEntityがあります。例:

[Authorize] 
public ActionResult Details(Entity entity) 
{ 
    ... 
    return View(); 
} 

私はこのエンティティをセッション中に保持し、モデルバインダーのこのパラメータをURLのidで埋めます。

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
{ 
    var httpContext = controllerContext.HttpContext; 
    var values = httpContext.Request.RequestContext.RouteData.Values; 

    if (!values.ContainsKey("id")) return null; 

    var id = values["id"].ToString(); 
    var obj = httpContext.Session["Entities"]; 
    var list = (List<Entity>) obj; 
    return list?.SingleOrDefault(x => x.Id == id); 
} 

セッションオブジェクトが空のときにユーザーがアクションにアクセスしようとする可能性があります。たとえば、ユーザーは電子メールでURLを取得し、Entityをセッションに入れるコードを省略します。

このケースの最適な修正方法は何ですか?

1は、バインダー内のエンティティを取得して実装します。

var id = values["id"].ToString(); 
    var obj = httpContext.Session["Entities"]; 
    var list = (List<Entity>) obj; 
    var entity = list?.SingleOrDefault(x => x.Id == id); 

    if(null==entity){ 
     entity = repository.GetEntity(id); 
     //set entity in session 
    } 

    return entity; 

私はバインダーに余分な充填ロジックを実装する必要がありのため、この方法は厄介になります。また、バインダーにリポジトリを挿入することはできません。しかし、この方法は簡単で実装が簡単です。

2.バインダを除去し、いくつかの方法で取得、追加:私は今、リポジトリの注入を実施することができます

[Authorize] 
public ActionResult Details() 
{ 
    Entity entity = GetEntity(); 
    ... 
    return View(); 
} 
private Entity GetEntity() 
{ 
    var id = ... //get id from http request. 
    var list = (List<Entity>)Session["Entities"]; 
    var entity = list?.SingleOrDefault(x => x.Id == id); 

    if(null==entity){ 
     entity = repository.GetEntity(id); 
     //set entity in session 
    } 

    return entity; 
} 

:すべてのバインダーを外して、次の方法で、エンティティのすべてのアクションを変更

コードは安全ですが、醜く見えます。

どのソリューションが最適ですか?他の実装を見逃している可能性はありますか?

+0

あなたはオプション2が醜いと思うのはなぜ?これは通常のアプローチであり、ModelBinderはあなたのリポジトリを呼び出すべきではありません。そして、あなたのメソッドは 'id'のパラメータを持っていなければなりません。 –

+0

@StephenMuecke 'id'に関する良い点。それは普通のアプローチですが、エレガントに見えません。 – RredCat

答えて

1

この方法では、余分な埋め込み ロジックをバインダーに実装する必要があるため、厄介なように見えます。また、バインダーにリポジトリを挿入することはできません。

モデルバインダーで依存性注入が正しく実行されないことは間違いありません。あなたのバインダを登録するときに

public class MyModelBinder : DefaultModelBinder 
{ 
    private readonly Func<IRepository> repositoryProvider; 

    public MyModelBinder(Func<IRepository> repositoryProvider) 
    { 
     this.repositoryProvider = repositoryProvider; 
    } 

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var id = ... //get id from http request. 
     var list = (List<Entity>)Session["Entities"]; 
     var entity = list?.SingleOrDefault(x => x.Id == id); 

     if (null == entity) 
     { 
      IRepository repository = this.repositoryProvider(); 
      entity = repository.GetEntity(id); 
      //set entity in session 
     } 

     return entity; 
    } 
} 

と::しかし、あなたは、工場を使用することができ

ModelBinders.Binders[typeof(Entity)] = new MyModelBinder(
    () => DependencyResolver.Current.GetService<IRepository>() 
); 
関連する問題