繁体   English   中英

RESTful和存储库从另一个类型体系结构返回值

[英]RESTful and Repository returning values from another type architecture

简而言之,我有两个数据库表:语言和框架。 重要的是,表之间存在一对多关系(一种语言有很多框架)。 我正在设计一个RESTful(WebAPI2)服务来使用这些表中的信息。 我正在使用存储库模式。 使用EF,我为该语言建立了导航属性,以达到其框架。

但是,应该如何在存储库中实现它。 在语言存储库中返回框架集合是否正确? 我想使用相同的WebAPI控制器来访问一种语言的框架,因为它提供了更简单的路由,而且我不确定这是否是正确的方法。

public class LanguagesController : ApiController
{
    private readonly IProgrammingLanguageRepository languages;

    public LanguagesController() : this(new ProgrammingLanguageRepository(new CVSystemDbContext()))
    {
    }

    public LanguagesController(ProgrammingLanguageRepository languagesRepository)
    {
        this.languages = languagesRepository;
    }

    [HttpGet]
    [Route("api/languages")]
    public IHttpActionResult GetAll()
    {
        return this.Ok(this.languages.GetAll());
    }

    [HttpGet]
    [Route("api/languages/{id:int}")]
    public IHttpActionResult GetById(int id)
    {
        return this.Ok(this.languages.GetById(id));
    }

    [HttpGet]
    [Route("api/languages/{id:int}/frameworks")]
    public IHttpActionResult GetByLanguage(int id)
    {
        ----
    }
}

另一方面,如果我在框架存储库中实现它(通过使用上下文中其他表中的navigation属性或通过id扫描),则应在框架WebAPI控制器中使用一些讨厌的路由(例如“ api” / frameworks / bylanguage / {id}“),这似乎也不正确。

我认为,要使RESTful服务尽可能整洁,这是在业务实体的基础上定义api控制器的最佳方法。 也就是说,您应该定义一个控制器来分别对languagesframeworks执行CRUD操作,如下所示:

public class LanguagesController : ApiController
{
    public IHttpActionResult Get(int id)
    {
        // logic to query and return a language by id
    }

    public IHttpActionResult GetAll()
    {
        // logic to query all (and possibly paginate) all the languages
    }
}

public class FrameworksController : ApiController
{
    public IHttpActionResult Get(int id)
    {
        // logic to query and return a framework by id
    }

    public IHttpActionResult GetByLanguage(int id)
    {
        // logic to return the frameworks of a specific language
    }

    public IHttpActionResult GetAll()
    {
        // logic to query all (and possibly paginate) all the frameworks
    }
}

我的意思是,对于RESTful服务,最好不要假设它们如何消耗返回的数据。 也就是说,您不应该假设在所有显示语言的地方都同时显示了框架。 例如,假设某些客户以表格形式列出了语言。 在其中包含框架的情况下,UI也将变得非常凌乱。 最好让用户选择一种语言并分别显示详细信息,例如在模式窗口中。 毕竟,RESTful服务的重点是尽可能细化地提供数据,而不是根据您的特定视图进行调整。 它们旨在将数据提供给各种支持HTTP的设备和软件-包括浏览器和智能手机应用程序。 如果您只想使用AJAX调用提供一些适合您的视图的数据,最好在常规MVC控制器上定义响应ajax调用并返回JsonResult操作方法。

我还要在这里指出的一件事是,您不应在服务中返回数据库实体。 我会提到两个+一个原因:

  • 安全性:不受任何控制地返回数据库实体意味着,每次修改数据模型时,这些更改都会反映在发送回客户端的数据中。 这是因为将您的数据转换为所需格式的序列化程序并不知道要包含哪些数据-除非您向其中添加属性,否则在这种情况下不应该这样做,因为包含实体的项目不应依赖于Web特定于api的程序集。 因此,如果您修改实体,使其中的一些实体包含某种敏感数据,则该数据也将包含在响应中。 在您的特定域中可能不必担心这件事,但是您应该记住这一点。
  • 域遍历:转换数据的序列化程序(除非我使用上一个项目要点中说明的有问题的属性另外指示),只需将其找到的每个属性递归转换为所需的格式,例如JSON。 通常,您将拥有比问题中描述的更多的实体-用户(包含敏感数据,例如密码哈希) ,管理数据以及您能想到的任何东西。 数据模型没有连接的情况很少见,也就是说,可以通过遍历一个或多个导航属性从任何其他实体访问任何实体。 因此,如果未正确告知序列化器要包含和转换的数据,它将仅递归地包含所有连接的实体。 由于通常已连接数据模型,因此,这仅意味着每个表的每条记录都将被包含在内,这将导致堆栈溢出异常或响应消息太大。
  • 安全性和域遍历相结合:第一个问题和第二个问题意味着,如果您的数据库中的数据不足以容纳单个响应,并且它们都只是被序列化了,那么任何敏感数据(例如,用户数据,密码哈希等)都将包含在内,而无需您甚至意识到了这一点。

简而言之,要解决此问题,您应该定义一些类,这些类准确地描述了将哪些数据发送回客户端,并仔细实现了如何选择它们的逻辑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM