当前位置: 首页 > news >正文

记一次通过c#运用GraphQL调用Github api

阅读目录

  • GraphQL是什么
  • .net下如何运用GraphQL
  • 运用GraphQL调用Github api
  • 结语

 

一、Graphql是什么

  最近在折腾使用Github api做个微信小程序练练手,本篇文章就是在这个过程中记录。

  直接先看下GraphQL的语法风格,感受一下:

query {
  repository(owner:"octocat", name:"Hello-World") {
      id
  }
}

  这是最最最简单的一个运用示例,效果上等价于http://graphqlapi.xxx.com/query/repository?owner=octocat&name=Hello-World ,返回的内容格式是这样:

{
  "data": {
    "repository": {
      "id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5"
    }
  }
}

  再看下稍微复杂点的查询方式:

query {
  repository(owner:"octocat", name:"Hello-World") {
    issues(last:20, states:CLOSED) {
      edges {
        node {
          title
          url
          labels(first:5) {
            edges {
              node {
                name
              }
            }
          }
        }
      }
    }
  }
}

  这是一个多级对象嵌套的查询,这里就不继续展开了。关于egde和node在下文会有少许讲解。对GraphQL有兴趣进行更深入了解的可以自行研究学习,我自己也是刚入门,不坑大家了:),官网是http://graphql.org/(这个可能打不开,可以打开国内的地址http://graphql.cn),Facebook发布的规范在 http://facebook.github.io/graphql/October2016/。

  GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。

 

二、.net下如何运用GraphQL

  由于我需要做一个定时任务将github上的数据定时拉到本地,所以自然的选择了后端处理的方式。找了一下.net下的GraphQL客户端,用了这个graphql-client。代码如下:

var heroRequest = new GraphQLRequest
                {
                    Query = graphql   //这里填写query的内容。
                };

var graphQLClient = new GraphQLClient("https://api.github.com/graphql");

graphQLClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("Safari", "537.36"));   
//上面这行很关键,UserAgent一定要写上,要不然会出现403错误,花了好久才找到这个问题。
graphQLClient.DefaultRequestHeaders.Add(
"Authorization", "bearer token"); //这里的token是个占位,实际需要在Github上生成。 var graphQLResponse = graphQLClient.PostAsync(heroRequest).Result;

  关于token的生成以及其它的一些环境准备工作,在github上有详细的描述,参见:https://developer.github.com/v4/guides/forming-calls/#authenticating-with-graphql。

  重要的事情说3遍:UserAgent一定要写上!! UserAgent一定要写上!! UserAgent一定要写上!!

 

三、运用GraphQL调用Github api

   Github提供的API和相关文档在https://developer.github.com/v4/ 右侧的目录树上,这次笔者需要拉取github的大量repository库,所以用到的search接口(但是很奇怪,这个接口在文档中并没有列出来,也不知道为什么)。建议大家可以先在Github提供的explorer中先测试和验证,OK了在把代码写到实际的项目中。

  接着,笔者在实现自己需要的功能时又学习了2个概念,才能正常开展下面的工作。第一个是edge与node的概念,edge可以理解为一个分页对象,其中除了包含实际的数据外还有一个cursor(返回的每条数据的唯一标识,如果要分页的话用得到这个数据,配合before与after关键字来使用)字段,实际数据就是用node表示的。

  另外GraphQL是强类型的,所以当笔者用到的search返回的结果并不是一个明确的数据对象时,先需要通过node下的__typename字段来获得实际的对象是什么。代码如下:

query {
  search(query:"language:c#",type:REPOSITORY,first:1){
    edges{
      cursor,
      node{
        __typename
      }
    }
  }
}

  得到的结果是:

{
  "data": {
    "search": {
      "edges": [
        {
          "cursor": "Y3Vyc29yOjE=",
          "node": {
            "__typename": "Repository"
          }
        }
      ]
    }
  }
}

  得到的实际的数据对象是Repository之后,通过查阅Github Api的文档得到该对象有哪些字段,并且从中选择需要的字段即可。这个就是GraphQL的设计天然优势之一,按需获取。单在接下去运用的时候又需要引入一个新的概念fragment,这个可以理解为一个模板,通过这个模板来向服务端指明需要获取的数据字段。代码如下:

fragment repFragment on Repository {
  name,
  forkCount,
  url,
  createdAt,
  updatedAt,
  licenseInfo{  //对象嵌套
    nickname    //licenseInfo的nickname字段
  },
  stargazers{   //对象嵌套
    totalCount  //stargazers的totalCount字段
  }
}

query {
  search(query:"language:c#",type:REPOSITORY,first:100){
    edges{
      cursor,
      node{
        __typename
        ...repFragment
      }
    }
  }
}

   好了,这样就得到我需要的结果了。

  下面附上笔者做的Demo:https://github.com/ZacharyFan/GitHubRanking,其中的token在配置文件中自行替换即可。

 

四、结语

  最后附带提一下,GraphQL的出现,主要的场景还是在于赋能前端开发,赋予了前端开发者自由组织和定制请求数据的能力。这是一个将前后端分离后的界限偏向前端的框架,所以直接在前端通过GraphQL访问后端数据是个人比较推崇的方式。目前前端非常火热的GraphQL框架也不少,主流的就是下面2个: apollo(https://github.com/apollographql/apollo-client)、relay(https://github.com/facebook/relay)。

  GraphQL虽好,但是要真正在中大型项目中运用GraphQL,还有有很大的困难的,服务端需要支持到GraphQL的规范格式进行数据输出,我认为需要付出的成本可不小。哪怕的架设一层中间层,也需要解决诸如分发、聚合和性能等问题。

 

 

作者:Zachary_Fan
出处:http://www.cnblogs.com/Zachary-Fan/p/CsharpGraphql.html

 

 

▶关于作者:张帆(Zachary,个人微信号:Zachary-ZF)。坚持用心打磨每一篇高质量原创。欢迎扫描右侧的二维码~。

定期发表原创内容:架构设计丨分布式系统丨产品丨运营丨一些思考。

 

如果你是初级程序员,想提升但不知道如何下手。又或者做程序员多年,陷入了一些瓶颈想拓宽一下视野。欢迎关注我的公众号「跨界架构师」,回复「技术」,送你一份我长期收集和整理的思维导图。

如果你是运营,面对不断变化的市场束手无策。又或者想了解主流的运营策略,以丰富自己的“仓库”。欢迎关注我的公众号「跨界架构师」,回复「运营」,送你一份我长期收集和整理的思维导图。

 

相关文章:

  • vue中嵌套页面(iframe)
  • nodejs+mongoose+blog
  • mysql查询两个日期之间相差多少天?
  • 数字货币交易界面数字格式化
  • mybitis懒加载Could not write JSON:No serializer...
  • srand rand
  • 简析gRPC client 连接管理
  • Java应用性能调优
  • BOM和DOM
  • Linux top命令的用法详细详解
  • StringUtils中常用方法leftPad(),rightPad(),center()
  • docker的持久化存储和共享存储和网络架构
  • 项目经理需了解的技术
  • HTTP头和网页分离方法
  • 架构师成长之路-基于android fragment通信的面向对象的万能接口
  • 时间复杂度分析经典问题——最大子序列和
  • [笔记] php常见简单功能及函数
  • “大数据应用场景”之隔壁老王(连载四)
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • Javascript 原型链
  • Vue 2.3、2.4 知识点小结
  • yii2中session跨域名的问题
  • 从零开始的无人驾驶 1
  • 对超线程几个不同角度的解释
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 聊聊flink的TableFactory
  • 树莓派 - 使用须知
  • 我感觉这是史上最牛的防sql注入方法类
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • 函数计算新功能-----支持C#函数
  • ​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】
  • ​HTTP与HTTPS:网络通信的安全卫士
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (Redis使用系列) Springboot 整合Redisson 实现分布式锁 七
  • (第27天)Oracle 数据泵转换分区表
  • (附源码)ssm高校志愿者服务系统 毕业设计 011648
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (一)WLAN定义和基本架构转
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET 8.0 中有哪些新的变化?
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .NET MVC第五章、模型绑定获取表单数据
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地定义和使用弱事件
  • /var/lib/dpkg/lock 锁定问题
  • []C/C++读取串口接收到的数据程序
  • [ActionScript][AS3]小小笔记
  • [Android 13]Input系列--获取触摸窗口
  • [Angular 基础] - 表单:响应式表单
  • [BZOJ3211]:花神游历各国(小清新线段树)