在找到将Services / ViewModel放入MVC应用程序的正确位置时遇到问题

时间:2011-04-26 18:39:23

标签: asp.net-mvc-3 s#arp-architecture

我有一个带有以下项目/图层的S#arp MVC应用程序:

  • 核心(型号)
  • 数据
  • 网络(查看)
  • 控制器
  • 服务

显示问题的一个例子:
我有一个模型 Ticket

public class Ticket : Entity
{
     public virtual string Summary { get; set; }
     public virtual string Description { get; set; }       
     public virtual DateTime CreateOn { get; set; }        
     public virtual DateTime UpdatedOn { get; set; }
     public virtual User CreatedBy { get; set; }
     public virtual User AssignedTo { get; set; }
     public virtual Priority Priority { get; set; }        
     public virtual Status Status { get; set; }        
}

它位于Core项目中......

到我的视图创建(票证)我需要 CreateTicketViewModel

public class CreateTicketVM
{
     [Required(ErrorMessage = "Required.")]
     public string Summary { get; set; }

     [Display(Required(ErrorMessage = "Required.")]
     public string Description { get; set; }

     [Required(ErrorMessage = "Required.")]
     public int AssignedToId { get; set; }     

     [Required(ErrorMessage = "Required.")]
     public int PriorityId { get; set; }

     [Required(ErrorMessage = "Required.")]
     public virtual int StatusId { get; set; }      

     public IList<User> Users { get; set; }       
     public IList<Priority> Priorities { get; set; }
     public IList<Status> Status { get; set; }        
}

它位于Controller项目......

到目前为止一切都很好......但在我的TicketController中,我需要填写所有CreateTicketVM列表(View中的下拉列表)。

所以我创建了一个 TicketService

public class TicketService : ITicketService
{       
     readonly IRepository<User> userRepository;
     readonly IRepository<Priority> priorityRepository;
     readonly IRepository<Status> statusRepository;
     ...     

     public CreateTicketVM CreateNewCreateTicketVM()
     {
         var _ticket = new CreateTicketVM();
         _ticket.Priorities = priorityRepository.GetAll();
         _ticket.Status = statusRepository.GetAll();
         _ticket.Users = userRepository.GetAll();
          _ticket.Categories = categoryRepository.GetAll();
          return _ticket;
     }
}

它位于服务项目......

问题在于接口ITicketService:

public interface ITicketService
{
    CreateTicketVM CreateNewCreateTicketVM();
}

它位于Core项目中......但Core Project不能包含Controller项目(CreateTicketVM)......

那么,我该如何处理呢?

由于

3 个答案:

答案 0 :(得分:7)

我不会在您的服务上放置CreateNewCreateTicketVM方法,而是在Controllers项目中为此创建一个增强的查询对象。然后,服务层只关注行为。

请参阅我的博文:

http://www.yellowfeather.co.uk/2011/03/enhanced-query-objects-with-sharp-architecture/

和Ayende的评论:

http://ayende.com/Blog/archive/2011/04/01/code-review-sharparchitecture.multitenant.aspx

答案 1 :(得分:2)

克里斯钉了那一个。使用查询对象直接投影到视图模型中。

答案 2 :(得分:1)

当你返回一个ViewModel(或者一个DTO,名字并不重要)时,填充了ILists只是为了显示在视图中,你已经从“语义”的角度紧紧地耦合到你的视图

这不是你在这里工程的东西,用较少的项目无法解决,例如:

  • 核心:可与其他应用共享的基础架构块
  • MyApp:您的应用程序的特定代码,以命名空间命令
    • MyApp.Data
    • MyApp.Services(服务接口)
    • MyApp.Services.Implementations(如果你真的想要分开)
  • MyApp.Web
    • MyApp.Web.Models
    • MyApp.Web.Controllers

MyApp.Web可以是一个MVC项目,或者如果你愿意,可以是2个项目,一个带控制器的c#库和一个只有视图的MVC项目。

在这种情况下,我认为让服务层构建ViewModel太过分了。这应该在您的控制器中完成,或者更好,通过AutoMapper等工具完成。

服务层应该有一些业务职责:“这个用户可以在这个精确的时间为这个分配票证吗?”例如。

此外,Ayende有一篇很好的博客文章:http://ayende.com/Blog/archive/2011/03/16/architecting-in-the-pit-of-doom-the-evils-of-the.aspx

不要忘记:KISS