Reputation: 10078
I am developing ASP.NET Core application. To keep controllers lean, most of the data manipulation is done in ViewModels. Everything works fine - the two problems, however, are
ViewModels don't have access to ControllerContext information (or I can't figure out how to get it). For example, Session, User and whatever else Controller gets for free.
ViewModels don't accept Dependency Injection (again, or I can't figure out how to pass it along). For example, if I have constructor MyController(ApplicationDbContext db)
I get db
passed without any problems. However, if I have ComplexViewModel(ApplicationDbContext db)
I get null
passed in. Obviously, I have exactly the same services.AddDbContext<ApplicationDbContext>()
in Startup
Right now I am passing whatever is required from Controller to ViewModel explicitly. But it feels that there should be a better way.
Upvotes: 0
Views: 940
Reputation: 218852
View models are supposed to be simple POCOs to transfer data between the views and action methods. I think it is a bad idea to mix all your business logic (or even data access) to view models. You may consider doing that in services. You can inject this services to your controllers.
For example.
Yo get a User information, you may consider creating a service
public interface IUserService
{
UserDto GetUser(int id);
}
public class UserService : IUserService
{
IUserDataAccess userDataAccess;
public UserService(IUserDataAccess userDataAccess)
{
this.userDataAccess=userDataAccess;
}
public UserDto GetUser(int id)
{
// with this.userDataAccess, get a User and map to UserDto
// to do : return something
}
}
So your controllers will stay lean
public class UserController : Controller
{
private readonly IUserService userService;
public UserController(IUserService userService)
{
this.userService = userService;
}
public ActionResult Details(int id)
{
var userDto= this.userService.GetUser(id);
return View(userDto);
}
}
Now you can have a UserDataAccess
which query your data and inject that to the UserService
class.
With this approach your view model does not have any idea what data access technology you are using. Imagine tomorrow you decided to ditch EF for performance reason and want to switch to Dapper, you simply need to create a new implementation of your IUserDataAccess
called "DapperUserDataAccess
" and udpate your DI config registration to use that. No other code change :)
Upvotes: 1