Domanda

Nel mio ASP.net MVC app Sto usando un livello di servizio e repository per mantenere il mio controller sottile. A dettagli tipici letti Visualizza solo assomiglia a questo:

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

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

Servizio di livello:

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

Passando dal livello di servizio al modello vista è abbastanza facile a causa della automapper, che può appiattire le cose abbastanza facilmente. Spostare l'altro direttamente, dal modello al fine di passare nel mio livello di servizio è dove faccio fatica a trovare una buona soluzione.

In una situazione come un'azione di Crea, che cosa è un approccio buono per questo?

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

    // TODO

    return RedirectToAction("Index");
}

Sono abbastanza sicuro che il livello di servizio non deve sapere nulla di modelli vista, ma ho anche non credo che automapper funziona bene in questo scenario sia, dato che non è bravo a prendere un modello piatto e trasformandolo in un oggetto complesso.

Che cosa dovrebbe il mio sguardo di controllo, come per comunicare con il livello di servizio? Voglio mantenere il codice nel controller il più leggero possibile.

È stato utile?

Soluzione

Si potrebbe definire una mappatura bidirezionale e poi il contrario:

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

o se si sta aggiornando un soggetto si potrebbe voler prima per andare a prendere l'entità esistente che si desidera aggiornare dal servizio:

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

Altri suggerimenti

L'unico modo che ho visto fare finora è quello di creare manualmente un gruppo di classi modello di trasformazione, per esempio:

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

E un'altra implementazione del trasformatore di tornare indietro l'altro modo (ViewModel -> DataModel). E avendo il controller sa di chiamare il corretto trasformatore.

I +1 tua domanda perché mi piacerebbe vedere un bel modo pulito per fare anche questo, senza dover scrivere manualmente un mucchio di codice per mappare modelli.

If your service layer is solely dedicated to support your MVC application and no other clients you could consider using the objects passed through and from your service layer as part of your viewmodels. This would obviate the need to automap the inbound calls as you'd be sending in the actual objects required from the controller.

You could also consider not having the services return domain objects, this would mean that the automapping should be invoked with the service methods rather than the controller actions.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top