MVC - controller for service level communications

In my ASP.net mvc application, I use the service level and repositories so that my controllers are thin. A typical read-only view is as follows:

public ActionResult Details(int id) { var project = _projectService.GetById(id); return View(Mapper.Map<Project, ProjectDetails>(project)); } 

Service Level:

 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 a service level to a presentation model is quite simple because of the automapper, which can easily smooth things out. Moving another direct one from the view model to go to my service level is where I struggle to find a good solution.

In a situation like the 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 am sure that the service level should not know anything about presentation models, but I also do not think AutoMapper works well in this scenario, since it is not very good at accepting a flat model and turning it into a complex object.

How should my dispatcher interact with the service level? I want the code in the controller to be as light as possible.

+6
source share
3 answers

You can define a bi-directional display, and then go the other way:

 [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 object, you can first get the existing object 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"); } 
+5
source

The only way I've seen this so far is to manually create a group of model transformation classes, for example:

 public interface ITransformer<out To, in From> where To : class { To Transform(From instance); } public class SomeDataToSomeViewModelTransformer : ITransformer<SomeViewModel, SomeDataModel> { public SomeViewModel Transform(SomeDataModel instance) { return new SomeViewModel { InvitationId = instance.Id, Email = instance.EmailAddress, GroupId = instance.Group.Id }; } } 

And another Transformer implementation to go back the other way ( ViewModel -> DataModel ). And have a controller to trigger the correct transformer.

I +1 your question, because I would like to see a good clean way to do this too, without having to manually write a bunch of code to map models.

+1
source

If your service level is intended solely to support your MVC application and other customers, you might consider using objects passing through and from your service level as part of your viewing models. This eliminates the need to automate incoming calls, since you are sending the actual objects required by the controller.

You might also think that services do not return domain objects, which would mean that automation should be called using service methods, not controller actions.

0
source

Source: https://habr.com/ru/post/908721/


All Articles