我有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;
}
我现在可以实现存储库的注入,代码是安全的,但看起来很难看。
哪种解决方案最好?我有可能错过任何其他实施吗?
答案 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>()
);