Asp.net mvc ASP.NET MVC-服务层<-&燃气轮机;控制器

Asp.net mvc ASP.NET MVC-服务层<-&燃气轮机;控制器,asp.net-mvc,controller,dto,service-layer,Asp.net Mvc,Controller,Dto,Service Layer,假设您正在实现自己版本的stackoverflow(再次,是的) 您的服务提供了所有必需的功能,如: class Question { ... } // EF entity class Answer { ... } // EF entity interface IStackoverflowService { void PostQuestion(Question question); void PostAnswer(Answer answer); void UpdateQ

假设您正在实现自己版本的stackoverflow(再次,是的)

您的服务提供了所有必需的功能,如:

class Question { ... } // EF entity
class Answer { ... } // EF entity

interface IStackoverflowService
{
    void PostQuestion(Question question);
    void PostAnswer(Answer answer);
    void UpdateQuestion(Question question);
    ...
}
interface Question
{
    int Id { get; set; }
    User Poster { get; set; }
    DateTime Posted { get; set; }
    DateTime? Edited { get; set; }
    string Title { get; set; }
    string Text { get; set; }
    IQueryable<Answer> Answers { get; set; }
    ...
}
    MyCompany.Data // Data layer namespace containing EF EDMX file / Codefirst / ADO.Net, whatever you want.
    class User { } // EF Entity

MyCompany.Business // Business layer namespace containing business level factory interfaces and classes that expose their own business objects (some are directly mapped to the DB, most are not). All members expose POCO objects

class NewUser { } // POCO class RegisteredUser { } // POCO interface IAccountFactory {
    void AddUser(NewUser user);
    RegisteredUser GetUser(int id); } // factory interface class AccountFactory : IAccountFactory // Service provider

MyCompany.MVC // Presentation layer containing controllers and views. Controllers expose POCO objects from the business layer to the Views.
这似乎很简单,一般来说我认为这是个好主意。我唯一不喜欢的是,客户端代码(ASP.NET MVC控制器)可以直接访问
问题
s和
答案
s。假设我们在发布问题和答案时遇到了一些棘手的问题。将此逻辑集中在服务层上的“单个位置”是个好主意。如果您的客户机代码可以访问
问题
s,有一天可能会有人决定在您的控制器中添加“一点逻辑”,这基本上是个坏主意

我正在考虑定义一些DTO,这些DTO将成为服务接口的一部分,因此客户机代码只能与这些包含“恰到好处的细节”的DTO一起工作

假设您的问题实体定义如下:

class Question { ... } // EF entity
class Answer { ... } // EF entity

interface IStackoverflowService
{
    void PostQuestion(Question question);
    void PostAnswer(Answer answer);
    void UpdateQuestion(Question question);
    ...
}
interface Question
{
    int Id { get; set; }
    User Poster { get; set; }
    DateTime Posted { get; set; }
    DateTime? Edited { get; set; }
    string Title { get; set; }
    string Text { get; set; }
    IQueryable<Answer> Answers { get; set; }
    ...
}
    MyCompany.Data // Data layer namespace containing EF EDMX file / Codefirst / ADO.Net, whatever you want.
    class User { } // EF Entity

MyCompany.Business // Business layer namespace containing business level factory interfaces and classes that expose their own business objects (some are directly mapped to the DB, most are not). All members expose POCO objects

class NewUser { } // POCO class RegisteredUser { } // POCO interface IAccountFactory {
    void AddUser(NewUser user);
    RegisteredUser GetUser(int id); } // factory interface class AccountFactory : IAccountFactory // Service provider

MyCompany.MVC // Presentation layer containing controllers and views. Controllers expose POCO objects from the business layer to the Views.
当有人打开页面检查问题时,会出现更多的细节,如
发布的
编辑的

class QuestionDetailsDTO
{
    User Poster { get; set; }
    string Title { get; set; }
    string Text { get; set; }
    DateTime Posted { get; set; }
    DateTime? Edited { get; set; }
}

等等。这是一个好的做法还是你认为这是过度工程?这里常见的方法是什么?

我最近使用了大量的Ninject和AutoMapper实现了与您所说的几乎完全相同的方法。我的逻辑结构如下:

class Question { ... } // EF entity
class Answer { ... } // EF entity

interface IStackoverflowService
{
    void PostQuestion(Question question);
    void PostAnswer(Answer answer);
    void UpdateQuestion(Question question);
    ...
}
interface Question
{
    int Id { get; set; }
    User Poster { get; set; }
    DateTime Posted { get; set; }
    DateTime? Edited { get; set; }
    string Title { get; set; }
    string Text { get; set; }
    IQueryable<Answer> Answers { get; set; }
    ...
}
    MyCompany.Data // Data layer namespace containing EF EDMX file / Codefirst / ADO.Net, whatever you want.
    class User { } // EF Entity

MyCompany.Business // Business layer namespace containing business level factory interfaces and classes that expose their own business objects (some are directly mapped to the DB, most are not). All members expose POCO objects

class NewUser { } // POCO class RegisteredUser { } // POCO interface IAccountFactory {
    void AddUser(NewUser user);
    RegisteredUser GetUser(int id); } // factory interface class AccountFactory : IAccountFactory // Service provider

MyCompany.MVC // Presentation layer containing controllers and views. Controllers expose POCO objects from the business layer to the Views.
我认为这一点也不过分——是的,它需要更长的时间来编写,但AutoMapper基本上为您消除了大部分繁琐的工作


我的一位同事非常热衷于控制反转,这显然解决了这个问题。。。尽管我还没有完全了解它:)

实现DTO并不能阻止某人只是在控制器上“添加一点逻辑”。MVC是它自己的范例,我希望人们能够意识到这一点,停止尝试添加n层概念。问题不在于MVC,而在于“MVC+BL”控制器中“+”的符号应该包含关于作为控制器一部分的操作的业务逻辑,模型应该封装其他业务逻辑。除非您需要连接到WCF或其他服务来访问您的数据,在这种情况下,您可以将其封装在EF中。不需要在单独的程序集中使用PL/BL/DL进行n层BL抽象。MVC模式非常清楚什么会发展到哪里。