ASP.NET MVC设计模式最佳实践与服务
我有一个ASP.NET MVC 3应用程序。
我有一个Model
, ViewModel
, View
, Controller
。
我使用Ninject
作为IoC。
我的Controller
使用ViewModel
将数据传递给View
。
我已经开始使用Service
(具体和接口类型)从ViewModel
获取信息并对数据库进行查询以对其进行操作。
我可以使用相同的Service
来设置ViewModel
吗? 或者这是否违背设计模式?
即我可以抽象在Service
层中设置ViewModel
吗?
脚本
情景是; 我的Model
有很多对其他Models
的引用,所以当我在控制器中设置ViewModel
时,它是详细的,我觉得Controller
做得太多了。 所以我希望能够做到这样的事情:
var vm = _serviceProvider.SetupViewModel(Guid model1Id, Guid model2Id, /*etc..*/)
ServiceProvider
的SetupViewModel
函数如下所示:
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
真的非常大!
我使用1个ViewModel
进行创建/编辑操作。 我没有在其他地方重用ViewModel
。
我会让服务层返回一个域模型并将其映射到控制器中的ViewModel。
这样,您可以使用具有多个ViewModel的服务方法,例如桌面和移动视图。
您可以通过在ViewModel中创建一个采用域模型的构造函数,让AutoMapper为您完成繁重的工作或手动完成。
域名模型:
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 Orders { get; set; } }
ViewModel:
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 Orders { get; set; } }
编辑:AutoMapper示例:
AutoMapper配置文件,包含从Customer
到CustomerWithOrdersModel
的映射:
public class ViewModelProfile : Profile { public override string ProfileName { get { return "ViewModel"; } } protected override void Configure() { CreateMap() .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(customer); } public static Customer ToEntity(this CustomerWithOrdersModel customerWithOrdersModel) { return Mapper.Map(customerWithOrdersModel); } }
控制器动作:
public ActionResult Details(int customerId) { Customer customer = _customerService.GetById(customerId); CustomerWithOrdersModel customerWithOrders = customer.ToModel(); return View(customerWithOrders); }
如果您创建从CustomerWithOrdersModel
到Customer
的映射,则可以使用customerWithOrdersModel.ToEntity()
将其映射回域模型。
而已! 您可以从ViewModel中删除具有Customer
域模型的构造函数。
如果您将视图模型作为自己的项目并处理服务层中视图模型的映射和返回,我认为没有错。 为了分离关注点,您可以始终拥有另一个处理映射的组件。