• 在.NET中体验GraphQL


    前言

    以前需要提供Web服务接口的时候,除了标准的WEBAPI形式,还考虑了OData、GraphQL等形式,虽然实现思路上有很大的区别,但对使用方来说,都是将查询的主动权让渡给了前端,让调用方能够更加自由地发挥或者符合自己要求的数据。其中,OData作为传统REST WEBAPI的拓展,对外还是WEBAPI的形式,为了照顾到和第三方对接的兼容性,我最终使用了OData作为首选技术。

    OData在使用上方便性不言而喻,简直爱不释手,不过逐渐也发现一个问题:Mock不方便!前端常用的比如json-schema-faker无法识别OData的标记,返回的内容依旧是传统API返回的内容(无法输出@odata之类的内容)。

    P.S. 最近还非常烦恼和OData一起使用EF Core时,由于有导航属性(Navigation Property),mock框架会循环引用导致Maximum call stack size exceeded的问题。一直没有找好办法,如果有朋友知道,还请不吝赐教。

    于是和调用方的扯皮一直延续,最后还是先上线了后台暂时处理了这个问题。最近有一个想法浮到水面:反正mock是不可能mock了,调用方已经要恨死我了,就干脆点直接WebAPI形式也不要了,摊牌了。

    GraphQL

    GraphQL是Facebook推出的一项提供数据API的语言,和WEBAPI相比较,它有一些自己的特点,详细介绍可以看这里,最吸引我的地方,就是请求API可以一步到位,处理一些逻辑的时候,简单的一个API请求就可以得到所有的数据(当然使用OData的expand等查询也可以达到类似的效果),而且描述语言也比较简洁。这样调用方可以精确描述自己需要什么,接口返回不多不少刚刚好的数据,优雅!

    关于GraphQL的介绍,可以查看其他文章,不是本文的重点。

    体验

    使用GraphQL,.NET支持的有很多库,比较流行的,有GraphQL.NET和HotChocolate,作为一个肥宅,我就选HotChocolate作为主要使用的库,直接使用nuget安装即可。

    install-package HotChocolate.AspNetCore
    

    新建一个新的ASP.NET CORE空项目,添加HotChocolate.AspNetCore的nuget包,然后定义以下数据结构

    public class Class
    {
        public string Name { get; set; }
        public Teacher Teacher{get;set;}
    }
    public class Student
    {
        public string Realname { get; set; }
    
        public Class Class{get;set;}
    }
    public class Teacher
    {
        public string Realname { get; set; }
        public bool IsSupervisor{get;set;}
    }
    

    描述一个班级,教师和学生的关系,如果是REST API的话,一般需要三个接口表述三种不同的资源。GraphQL只有一个Endpoint,这个就比较简单了。

    接下来定义暴露的接口:

    using System.Collections.Generic;
    
    
    using System.Linq;
    
    
    namespace Demo
    {
        public class Query
        {
            private List<Student> GetStudents()
            {
                List<Student> students = new List<Student>();
                students.Add(new Student
                {
                    Realname = "ZHANGSAN",
                    Class = new Class
                    {
                        Name = "GAOSAN",
                        Teacher = new Teacher { Realname = "LISI", IsSupervisor = false }
                    }
                });
                students.Add(new Student
                {
                    Realname = "ZHANGSAN2",
                    Class = new Class
                    {
                        Name = "GAOSAN1",
                        Teacher = new Teacher { Realname = "LISI", IsSupervisor = true }
                    }
                });
                return students;
            }
            public IEnumerable<Student> StudentInfo(string name)
            {
                if(string.IsNullOrWhiteSpace(name)) return GetStudents();
                return GetStudents().Where(w=>w.Realname == name);
            }
        }
    }
    

    提供了一个StudentInfo可以对外接口。

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGraphQLServer().AddQueryType<Query>();
    }
    
    //在configure中
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGraphQL();
    });
    

    然后然后直接F5运行,访问HotChocolate自带的分析器地址:http://localhost:5000/graphql/

    直接查询即可得到结果,换一种查询条件:

    可以发现,GraphQL返回的内容是可以由调用方进行定义的,你要啥它给啥,不用的字段你不写就不返回。很多时候,只要一次查询就能完成多次普通WebAPI请求才能达到的目标。(这个例子还不能表现出这个特点,有机会以后补充)。

    补充

    如果调用方不会GraphQL的话,不建议轻易上这个技术,因为他们来一句“这不是标准WEBAPI或者Webservice,我们调不了。”就把你噎死了。好多歹说就算终于上了,你还需要告诉清楚他们每一个接口的请求内容,这就纯粹给自己找事,体验太不好了。

    除非特殊说明,本作品由podolski创作,采用知识共享署名 4.0 国际许可协议进行许可。欢迎转载,转载请保留原文链接~喜欢的观众老爷们可以点下关注或者推荐~
  • 相关阅读:
    python走起之第十七话
    python走起之第十五话
    python走起之第十四话
    python走起之第十三话
    python走起之第十二话
    python走起之第十一话
    python走起之第九话
    python走起之第九话
    python走起之第八话
    python走起之第六话
  • 原文地址:https://www.cnblogs.com/podolski/p/14394764.html
Copyright © 2020-2023  润新知