In my ASP.net mvc app I am using a Service Layer and Repositories to keep my controllers thin. A typical details read only view looks like this:
public ActionResult Details(int id)
{
var project = _projectService.GetById(id);
return View(Mapper.Map<Project, ProjectDetails>(project));
}
Service Layer:
public class ProjectService : IProjectService
{
public Project GetById(int id)
{
var project = _projectRepository.GetProject(id);
// do some stuff
return project;
}
}
public class ProjectRepository : IProjectRepository
{
public Project GetProject(int id)
{
return context.Projects.Find(id);
}
}
Moving from the service layer to the view model is pretty easy because of automapper, which can flatten things pretty easily. Moving the other direct, from the view model to pass into my service layer is where I struggle to come up with a good solution.
In a situation like a Create action, what is a good approach for this?
[HttpPost]
public ActionResult Create(CreateProjectViewModel model)
{
if(!ModelState.IsValid)
{
return View(model);
}
// TODO
return RedirectToAction("Index");
}
I'm pretty sure that the service layer should not know anything about view models, but I also don't think that AutoMapper works well in this scenario either, since it's not good at taking a flat model and making it into a complex object.
What should my controller look like to communicate with the service layer? I want to keep the code in the controller as light as possible.
You could define a bidirectional mapping and then go the other way around:
[HttpPost]
public ActionResult Create(CreateProjectViewModel model)
{
if(!ModelState.IsValid)
{
return View(model);
}
Project project = Mapper.Map<CreateProjectViewModel, Project>(model);
// pass the project entity to your service layer
_projectService.Create(project);
return RedirectToAction("Index");
}
or if you are updating an entity you might first want to fetch the existing entity that you want to update from the service:
[HttpPost]
public ActionResult Update(CreateProjectViewModel model)
{
if(!ModelState.IsValid)
{
return View(model);
}
Project project = _projectService.GetById(model.Id);
Mapper.Map<CreateProjectViewModel, Project>(model, project);
// pass the project entity to your service layer
_projectService.Update(project);
return RedirectToAction("Index");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With