Felix Felix - 1 year ago 67
C# Question

Access controller data from ViewModel

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

  1. 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.

  2. 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
    passed without any problems. However, if I have
    ComplexViewModel(ApplicationDbContext db)
    I get
    passed in. Obviously, I have exactly the same
    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.

Answer Source

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)
  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 :)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download