模型绑定器中的填充实体与替换绑定器的外部方法

时间:2016-12-10 05:56:21

标签: c# asp.net-mvc modelbinders

我有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以执行操作,并省略将实体置于会话中的代码。

此案例的最佳解决方案是什么?

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。删除活页夹并添加一些get方法:

完全删除活页夹并以下一种方式更改Entity的所有操作:

[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; 
}

我现在可以实现存储库的注入,代码是安全的,但看起来很难看。

哪种解决方案最好?我有可能错过任何其他实施吗?

1 个答案:

答案 0 :(得分: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>()
);