比方说,我创建具有以下特征的“待办事项列表”的Web应用程序:ASP.NET MVC4库注入到控制器,取决于当前登录用户
- 有能力注册/登录用户每
- 用户有自己的TODO列表,这是独立于其他用户
所以我创建了一个简单的模型,具有类ToDoItem。
我想用好的做法,所以我创建了应该从数据库中获取TODO项目的通用资源库:
public interface IRepository<T>
{
IQueryable<T> FindAll();
IQueryable<T> Find(Expression<Func<T, bool>> predicate);
void Add(T newEntity);
void Remove(T entity);
T FindById(long id);
}
(实现与EF和代码第一种方法做,但现在这并不重要)
此存储库将被注入控制器,允许用户列出,添加,删除,编辑TODO项目。这是通过我创建的自定义控制器工厂完成的,该工厂使用Ninject DI容器将存储库接口解析为具体实现。 所以控制器看起来是这样的:
public class HomeController : Controller
{
IRepository<ToDoItem> _repository;
public HomeController(IRepository<ToDoItem> repository)
{
_repository = repository;
}
// list all TODO items for this user
[Authorize]
public ActionResult ListItems()
{
var todoItems = _repository.FindAll();
return View(todoItems);
}
}
我的问题是什么使只为当前登录的用户控制器回报TODO列表的最佳方式?理想情况下,我希望控制器能够与注入的存储库一起工作,并使用当前登录的用户进行预设。换句话说,我想避免这种代码在操作方法:
// list all TODO items for this user
[Authorize]
public ActionResult ListItems()
{
var todoItems = _repository.FindAll(User.Identity);
return View(todoItems);
}
我在想,可能的解决办法是使控制器工厂莫名其妙地知道哪些用户登录所以它会初始化具体的存储库和设置用户ID,以便控制器不必在每个操作方法中都这样做。这是否是一种好方法,如果是的话,我该如何实现它?如果不是,有什么更好的选择?
由于存储库注入到控制器中,使其生命周期与Web请求权绑定?但是,我想避免控制器的代码依赖于当前记录的用户和使用已经返回当前用户数据的存储库。例如,假设我没有多用户支持就首先创建了这个应用程序。现在我将如何扩展它以支持多用户最简单的方式?例如。控制器应保持不变,只更改存储库以返回当前登录用户的数据。希望这会更清楚我的问题... – matori82 2013-05-09 15:38:32
存储库的生活方式与Web请求无关;它可以例如具有单身生活方式,这意味着将相同的存储库实例注入到每个新创建的控制器实例中。我现在更了解你想做什么,但我不确定希望避免修改控制器代码是实现它的最好方法。话虽如此,“HttpContext.User”和“Thread.CurrentPrincipal”都应设置为代表当前用户的“IPrincipal”,以便您可以在存储库方法中使用这些... – 2013-05-09 15:48:00
注入“IPrincipal”或“IIdentity”可能会使存储库更易于测试,但这确实意味着存储库的生活方式需要根据每个Web请求(或更短)进行。 – 2013-05-09 15:49:38