views:

108

answers:

2

I'm wondering about a "best practice" using NHibernate, AutoMapper and ASP.NET MVC. Currently, i'm using :

class Entity
{
    public int Id { get; set; }
    public string Label { get; set; }
}

class Model
{
    public int Id { get; set; }
    public string Label { get; set; }
}

Entity and model are mapped like this :

Mapper.CreateMap<Entity,Model>();
Mapper.CreateMap<Model,Entity>()
    .ConstructUsing( m => m.Id == 0 ? new Entity() : Repository.Get( m.Id ) );

And in the controller :

public ActionResult Update( Model mdl )
{
    // IMappingEngine is injected into the controller
    var entity = this.mappingEngine.Map<Model,Entity>( mdl );

    Repository.Save( entity );

    return View(mdl);
} 

Is this correct, or can it be improved ?

A: 

I would inject the IMappingEngine into the controller, instead of the using the static Mapper class. You then get all the benefits of being able to mock this in your tests.

Take a look at this link by AutoMapper's creator,

http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/05/11/automapper-and-ioc.aspx

Castrohenge
yes could do this too.
mathieu
+1  A: 

that's how I was doing in a project:

public interface IBuilder<TEntity, TInput>
{
    TInput BuildInput(TEntity entity);
    TEntity BuildEntity(TInput input);
    TInput RebuildInput(TInput input);
}

implement this interface for each entity or/and for some group of entities you could do a generic one and use it in each controller; use IoC;

you put your mapping code in the first 2 methods (doesn't matter the mapping technology, you could even do it by hand) and the RebuildInput is for when you get the ModelState.IsValid == false, just call BuildEntity and BuildInput again.

and the usage in the controller:

        public ActionResult Create()
        {
            return View(builder.BuildInput(new TEntity()));
        }

        [HttpPost]
        public ActionResult Create(TInput o)
        {
            if (!ModelState.IsValid)
                return View(builder.RebuildInput(o));
            repo.Insert(builder.BuilEntity(o));
            return RedirectToAction("index");
        }

I actually do sometimes generic controller that is used for more entities like here: http://stackoverflow.com/questions/3413626/asp-net-mvc-generic-controller/3418849#3418849

Omu