当我想知道一些问题时,我开始重构一个使用MVC 6和Entity Framework 7的ASP.Net 5 Web应用程序。我的控制器当前通过依赖注入使用DbContext
实现来填充视图模型并返回它们以使用视图进行渲染。像:
public class UserController : Controller
{
[FromServices]
public MyContext myContext { get; set; }
//route which renders all users
public IActionResult Index()
{
var users = myContext.User.OrderBy(u => u.Name);
List<UserIndexViewModel> v = new List<UserIndexViewModel>();
foreach (var item in users)
{
v.Add(new UserIndexViewModel { Name = item.Name, City = item.City, DateOfBirth = item.DateOfBirth });
}
return View(v);
}
//route to edit user
public async Task<ActionResult> Edit(int id)
{
User user = await FindUserAsync(id);
UserEditViewModel v = new UserEditViewModel { Name = user.Name, City = user.City };
return View(v);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Update(int id, UserEditViewModel userModel)
{
User user = await FindUserAsync(id);
try
{
user.Name = userModel.Name;
user.City = userModel.City;
myContext.User.Attach(user);
myContext.Entry(user).State = EntityState.Modified;
await myContext.SaveChangesAsync();
return RedirectToAction("Index");
}
catch (Exception)
{
ModelState.AddModelError(string.Empty, "Unable to save changes.");
}
return View(userModel);
}
private Task<User> FindUserAsync(int id)
{
return myContext.User.SingleOrDefaultAsync(u => u.UserId == id);
}
}
我做了一些研究,发现了一些博客文章(like this),要求保持控制器清洁。好啊,为什么不?
我开始创建一种视图模型构建器,将逻辑从控制器方法中移出到视图模型构建器。在上面的链接文章中,提示为每个视图模型创建一个自己的视图模型构建器类 - 这在我眼中是有意义的。
对于模型User
,存在两个视图,因此存在两个视图模型(UserIndexViewModel
和UserEditViewModel
)。当我创建相关的视图模型构建器类时,它们应该从相同的(抽象)类派生,因为它可能是两个子类都需要一个辅助方法(如FindUserAsync()
- 在我的例子中并非如此但是想象一下)。所以我会有如下构造:
public interface IViewModelBuilder<TController, TViewModel>
{
TViewModel Build(TController controller, TViewModel viewModel);
Task<TViewModel > BuildAsync(TController controller, TViewModel viewModel);
}
public abstract class UserViewModelBuilder<TViewModel> : IViewModelBuilder<UserController, TViewModel> { ... }
public class UserIndexViewModelBuilder : SiteViewModelBuilder<UserIndexViewModel> { ... }
public class UserEditViewModelBuilder : SiteViewModelBuilder<UserEditViewModel> { ... }
一个模型的多个视图模型构建器所需的这个提到的函数应该在抽象类中实现(在我的例子中是UserViewModelBuilder
),对吗?
我是这样做的:
public abstract class UserViewModelBuilder<TViewModel> : IViewModelBuilder<UserController, TViewModel>
{
[FromServices]
public MyContext myContext { get; set; }
public abstract TViewModel Build(UserController controller, TViewModel viewModel);
public abstract Task<TViewModel> BuildAsync(UserController controller, TViewModel viewModel);
public Task<User> FindUserAsync(int id)
{
return myContext.User.SingleOrDefaultAsync(u => u.UserId == id);
}
}
因此,通过这个抽象类,我可以创建UserIndexViewModelBuilder
和UserEditViewModelBuilder
类的实现,以及将来的UserDeleteViewModelBuilder
和UserCreateViewModelBuilder
类...
现在的问题是:
DbContext
实现的正确位置吗?对我来说感觉不好。谢谢! : - )