模型活页夹中的填充实体与替换活页夹的外部方法
Filling entity in model binder vs external method that replace binder
我有 asp.net MVC 网络应用程序。它是一些实体的列表,用户可以在其中选择其中的一些实体并查看详细信息等。
此应用程序的大部分操作都有一些 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。删除活页夹并添加一些获取方法:
完全删除活页夹,并通过以下方式更改实体的所有操作:
[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;
}
我现在可以实现仓库注入了,代码是安全的,但是看起来很丑
哪种解决方案最好?有没有可能我错过了任何其他实施?
This way looks nasty because of I have to implement extra filling
logic in the binder. Also, I can't inject repository in the binder.
您说得对,依赖注入无法在模型绑定器中正确完成。但是你可以使用工厂:
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>()
);
我有 asp.net MVC 网络应用程序。它是一些实体的列表,用户可以在其中选择其中的一些实体并查看详细信息等。
此应用程序的大部分操作都有一些 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。删除活页夹并添加一些获取方法:
完全删除活页夹,并通过以下方式更改实体的所有操作:
[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;
}
我现在可以实现仓库注入了,代码是安全的,但是看起来很丑
哪种解决方案最好?有没有可能我错过了任何其他实施?
This way looks nasty because of I have to implement extra filling logic in the binder. Also, I can't inject repository in the binder.
您说得对,依赖注入无法在模型绑定器中正确完成。但是你可以使用工厂:
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>()
);