AutoMapper更新操作在ASP.NET MVC [英] AutoMapper Update Actions in ASP.NET MVC

查看:280
本文介绍了AutoMapper更新操作在ASP.NET MVC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能是一些比较简单的,但是我有点糊涂了,不能找到一个体面的例子。说我使用的视图模型和我的职务行为发生在该视图模式。通常,我会做大意如下的内容:

This is probably quite straight forward for some, however I'm a bit confused and can't find a decent example. Say I'm using view models and my POST action takes in that view model. Typically I would do something along the following lines:

    [HttpPost]
    public ActionResult Update(UserViewModel uvm)
    {
        User user = Mapper.Map<UserViewModel, User>(uvm);
        _repository.Update(user);

        return RedirectToAction("Index");
    }

尽管这不是的全貌。如果我只是更新我所映射,然后它会在数据库中摆脱有价值的数据,因为当然在这种情况下,我不更新的密码或其他细节的映射可以正常工作,但是。

Although this isn't the full picture. The mapping would work fine, however if I were to just update what I've mapped then it'd get rid of valuable data in the database because of course in this case I'm not updating the password or other details.

我的仓库看起来是这样的:

My repository looks something like this:

    public void Update(User user)
    {
        User u = Session.QueryOver<User>().Where(x => x.UserName == user.UserName).SingleOrDefault();

        if (u == null)
            throw new Exception("User not found");

        u.Forename = user.Forename;
        u.Surname = user.Surname;
        u.EmailAddress = user.EmailAddress;
    }

[我使用NHibernate所以它会在一次会话关闭回保存对象到DB(请求完成后)会自动给我。]

我的问题是,在我的仓库,我应该载入用户的实体,然后更新我想要的值,然后将其重新保存,还是有其他方法来做到这一点?我想问的原因是因为它似乎有点...手动如果你明白我的意思吗?也许是正确的,但我只是想看到这些意见,在这方面更有经验。

So my question is, in my repository should I load the "User" entity, then update the values I want, and then save it back, or is there another method to do this? The reason I ask is because it seems a bit... "manual" if you see what I mean? Perhaps it is correct, but I just wanted to see opinions of those with more experience in this area.

干杯

推荐答案

我用下面的办法:

[HttpPost]
public ActionResult Update(UserViewModel uvm)
{
    User user = _userRepository.FindById(uvm.Id);

    user.Forename = uvm.Forename;
    user.Surname = uvm.Surname;
    user.EmailAddress = uvm.EmailAddress;

    _userRepository.Update(user);

    return RedirectToAction("Index");
}


更新:

要解决有关 AutoMapper 的评论这里是如何进行操作:

To address the comments about AutoMapper here's how to proceed:

让我们来举个例子以下类:

Let's take for example the following classes:

public class UserViewModel
{
    public string Forename { get; set; }
    public string Surname { get; set; }
    public string EmailAddress { get; set; }
}

public class User
{
    public string Forename { get; set; }
    public string Surname { get; set; }
    public string EmailAddress { get; set; }

    public string Password { get; set; }
}

我们不希望在UI修改用户密码。因此,我们的前preSS我们打算AutoMapper:

We don't want to modify the user password in the UI. So we express our intention to AutoMapper:

Mapper
    .CreateMap<UserViewModel, User>()
    .ForMember(dest => dest.Password, opt => opt.Ignore());

和则:

[HttpPost]
public ActionResult Update(UserViewModel uvm)
{
    // Fetch the original model we would like to update
    User user = _userRepository.FindById(uvm.Id);

    Mapper.Map(uvm, user);
    // At this stage the user model will have its 
    // Forename, Surname and EmailAddress properties 
    // updated from the view model and its Password property
    // will remain the one we got from the repository

    _userRepository.Update(user);

    return RedirectToAction("Index");
}


更新2:


UPDATE 2:

要解决有关配置AutoMapper的评论我通常使用配置文件的问题:

To address the question in the comments about configuring AutoMapper I usually use Profiles:

public class UsersProfile : Profile
{
    protected override void Configure()
    {
        Mapper
            .CreateMap<UserViewModel, User>()
            .ForMember(dest => dest.Password, opt => opt.Ignore());    

        Mapper
            .CreateMap<User, UserViewModel>();
    }
}

,然后有哪些寄存器所有的映射器注册表类:

and then have a registry class which registers all the mappers:

public class MappingsRegistry
{
    public static void Configure()
    {
        Mapper.AddProfile(new UsersProfile());
        Mapper.AddProfile(new SomeOtherProfile());
        ...
    }
}

这是在的Application_Start 名为:

MappingsRegistry.Configure();

最后我的控制器必须映射引擎的引用:

Finally my controllers have a reference to the mapping engine:

public class UsersController : Controller
{
    private readonly IUsersRepository _repository;
    private readonly IMappingEngine _mappingEngine;
    public ContratsFCController(IUsersRepository repository, IMappingEngine mapperEngine)
    { 
        _repository = repository;
        _mapperEngine = mapperEngine;
    }

    [AutoMap(typeof(User), typeof(UserViewModel))]
    public ActionResult Update(int id)
    {
        var user = _repository.FindById(id);
        return View(user);
    }

    [HttpPost]
    public ActionResult Update(UserViewModel uvm)
    {
        if (!ModelState.IsValid)
        {
            return View(uvm);
        }
        var user = _repository.FindById(uvm.Id);
        _mapperEngine.Map(uvm, user);
        _repository.Update(user);
        return RedirectToAction("Index");
    }
}

现在所有剩下的就是需要指导的DI框架的 Mapper.Engine 属性传递给构造函数,并在单元测试显然与适当的模拟替换。

Now all that's left is to instruct your DI framework to pass the Mapper.Engine property to the constructor and in your unit tests obviously substitute them with an appropriate mock.

这篇关于AutoMapper更新操作在ASP.NET MVC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆