Question

Dans mon ASP.net mvc application J'utilise une couche de service et Référentiels pour garder mes contrôleurs minces. Une lecture voir seulement les détails typique ressemble à ceci:

public ActionResult Details(int id)
{
    var project = _projectService.GetById(id);

    return View(Mapper.Map<Project, ProjectDetails>(project));
}

couche de service:

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);
    }
}

Déplacement de la couche de service au modèle de vue est assez facile en raison de automapper, qui peut aplatir les choses assez facilement. Déplacement de l'autre directe, du modèle en vue de passer dans ma couche de service est l'endroit où je lutte pour trouver une bonne solution.

Dans une telle situation, une action Créer, ce qui est une bonne approche pour cela?

[HttpPost]
public ActionResult Create(CreateProjectViewModel model)
{
    if(!ModelState.IsValid)
    {
        return View(model);
    }

    // TODO

    return RedirectToAction("Index");
}

Je suis sûr que la couche de service ne doit pas savoir quoi que ce soit sur les modèles de vue, mais je ne pense pas que AutoMapper fonctionne bien dans ce scénario soit, étant donné que ce n'est pas bon à prendre un modèle plat et d'en faire un objet complexe.

Que dois mon regard du contrôleur comme pour communiquer avec la couche de service? Je veux garder le code dans le contrôleur le plus léger possible.

Était-ce utile?

La solution

Vous pourriez définir un mappage bidirectionnel puis aller dans l'autre sens:

[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");
}

ou si vous mettez à jour une entité que vous pourriez d'abord vouloir chercher l'entité existante que vous souhaitez mettre à jour du 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");
}

Autres conseils

La seule façon que je l'ai vu cela jusqu'à présent est de créer manuellement un tas de classes de transformation de modèle, par exemple:

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
            };
    }
}

Et une autre mise en œuvre du transformateur pour revenir dans l'autre sens (ViewModel -> DataModel). Et ayant le contrôleur sait appeler le transformateur correct.

Je +1 votre question parce que j'aimerais voir une belle façon propre à faire cela aussi, sans avoir à écrire manuellement un tas de code pour la carte des modèles.

Si votre couche de service est dédié à soutenir uniquement votre application MVC et pas d'autres clients, vous pouvez envisager d'utiliser les objets passés par et à partir de votre couche de service dans le cadre de vos viewmodels. Cela éviterait la nécessité d'Automap les appels entrants que vous seriez l'envoi des objets réels nécessaires à partir du contrôleur.

Vous pouvez également envisager pas avoir les services de retour des objets de domaine, cela signifierait que le AutoMapping devrait être appelé avec les méthodes de service plutôt que les actions du contrôleur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top