ASP.NET MVC设计模式与服务的最佳实践
本文关键字:最佳 服务 NET MVC 设计模式 ASP | 更新日期: 2023-09-27 18:21:42
我有一个ASP.NET MVC 3应用程序。
我有一个Model
,ViewModel
,View
,Controller
。
我使用Ninject
作为IoC。
我的Controller
使用ViewModel
将数据传递给View
。
我已经开始使用Service
s(具体类型和接口类型)从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的服务方法,例如桌面和移动视图。
您可以让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; }
}
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<Order> Orders { get; set; }
}
EDIT:AutoMapper示例:
AutoMapper配置文件包含从Customer
到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()));
}
}
CCD_ 28按照约定进行映射。
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);
}
如果创建从CustomerWithOrdersModel
到Customer
的映射,则可以使用customerWithOrdersModel.ToEntity()
将其映射回域模型。
就是这样!您可以从ViewModel中删除具有Customer
域模型的构造函数。
如果您将视图模型作为自己的项目,并在服务层中处理视图模型的映射和返回,我认为这没有错。为了分离关注点,您可以始终使用另一个组件来处理映射。