3

我有一个 ASP.NET MVC 3 应用程序。

我有一个Model, ViewModel, View, Controller.

Ninject用作 IoC。

Controller使用 aViewModel将数据传递给View.

我已经开始使用Services (具体和接口类型)从ViewModel数据库中获取信息并查询它来操作它。

我可以使用相同Service的设置ViewModel吗?还是这违背了设计模式的本质?

ViewModel即我可以在Service图层中抽象设置吗?

设想

场景是;myModel有很多对 other 的引用Models,所以当我ViewModel在控制器中设置时它是冗长的,我觉得Controller它做的太多了。所以我希望能够做类似的事情:

var vm = _serviceProvider.SetupViewModel(Guid model1Id, Guid model2Id, /*etc..*/)

中的SetupViewModel函数ServiceProvider如下所示:

public MyModelViewModel SetupViewModel(Guid model1Id, Guid model2Id, /*etc...*/)
{
    var vm = new MyModelViewModel();
    var model1 = _repository.Model1s.FirstOrDefault(x => x.Id.Equals(model1Id));
    var model2 = _repository.Model2s.FirstOrDefault(x => x.Id.Equals(model2Id));
// etc....

    vm.Model1 = model1;
    vm.Model2 = model2;

    return vm;
}

通过这样做,我还可以添加一些null条件,不用担心让我Controller真的真的很大!

我将 1ViewModel用于创建/编辑操作。我不重复使用ViewModel其他地方。

4

2 回答 2

5

我会让服务层返回一个域模型并将其映射到控制器中的 ViewModel。

通过这种方式,您可以使用具有多个 ViewModel 的服务方法,例如用于桌面和移动视图。

您可以让AutoMapper为您完成繁重的工作或手动完成,方法是在 ViewModel 中创建一个接受域模型的构造函数。

领域模型:

public class Customer
{
    public int Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string Telephone { get; set; }

    public string Email { get; set; }

    public virtual ICollection<Order> Orders { get; set; }
}

视图模型:

public class CustomerWithOrdersModel
{
    public CustomerWithOrdersModel(Customer customer)
    {
        Id = customer.Id;
        FullName = string.Format("{0}, {1}", customer.LastName, customer.FirstName);
        Orders = customer.Orders.ToList();
    }

    public int Id { get; set; }

    public string FullName { get; set; }

    public IEnumerable<Order> Orders { get; set; }
}

编辑:AutoMapper 示例:

AutoMapper 配置文件包含从 aCustomer到 a的映射CustomerWithOrdersModel

public class ViewModelProfile : Profile
{
    public override string ProfileName
    {
        get { return "ViewModel"; }
    }

    protected override void Configure()
    {
        CreateMap<Customer, CustomerWithOrdersModel>()
            .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => string.Format("{0}, {1}", src.LastName, src.FirstName)))
            .ForMember(dest => dest.Orders, opt => opt.MapFrom(src => src.Orders.ToList()));
    }
}

Id按约定映射。

的扩展方法ViewModelProfile

public static class ViewModelProfileExtensions
{
    public static CustomerWithOrdersModel ToModel(this Customer customer)
    {
        return Mapper.Map<CustomerWithOrdersModel>(customer);
    }

    public static Customer ToEntity(this CustomerWithOrdersModel customerWithOrdersModel)
    {
        return Mapper.Map<Customer>(customerWithOrdersModel);
    }
}

控制器动作:

public ActionResult Details(int customerId)
{
    Customer customer = _customerService.GetById(customerId);
    CustomerWithOrdersModel customerWithOrders = customer.ToModel();
    return View(customerWithOrders);
}

如果您创建一个从CustomerWithOrdersModelto的映射Customer,您可以使用customerWithOrdersModel.ToEntity()它来将其映射回域模型。

就是这样!您可以Customer从 ViewModel 中删除带有域模型的构造函数。

于 2013-07-08T17:32:37.357 回答
1

如果您将视图模型作为自己的项目并在服务层中处理视图模型的映射和返回,我认为这没有任何问题。为了分离关注点,您总是可以拥有另一个处理映射的组件。

于 2013-07-08T15:38:15.007 回答