ASP.NET Core中使用GraphQL


字段

我们已经很好的理解了GraphQL中的字段。在之前HelloWorldQuery的例子中,我们添加了2个字段hellohowdy. 它们都是标量字段。正如GraphQL官网文档中声明的那样

"At its simplest, GraphQL is about asking for specific fields on objects"

简单来说,GraphQL就是询问对象中的一些特定字段

来源: graphql.org

下面我们来为我们的实例程序添加一些复杂的类型。比如,现在我们需要编写一个库存系统,我们首先添加一个货物类Item, 其代码如下:

public class Item
{
public string Barcode { get; set; } public string Title { get; set; } public decimal SellingPrice { get; set; }
}

但是我们不希望直接针对这个对象创建查询,因为它不是一个GraphQL对象,它没有继承自ObjectGraphType, 为了创建一个GraphQL查询,我们需要创建一个新类ItemType, 它继承自ObjectGraphType类。

另外ObjectGraphType类是一个泛型类,所以这里我们需要指定它的泛型参数是Item

public class ItemType : ObjectGraphType<Item>
{
public ItemType()
{
Field(i => i.Barcode);
Field(i => i.Title);
Field(i => i.SellingPrice);
}
}

这里有2点需要注意。首先我们不在针对字段进行类型声明了。GraphQL库将实体类属性字段类型映射成GraphQL的内置类型。例如这里Barcode的类型string会被映射成GraphQL的内置类型StringGraphType。其次这里我们使用了Lambda表达式设置了实体类属性和GraphQL字段之间的映射, 这有点类似于数据库模型和ViewModel之间的转换的映射。

下一步,我们需要在HelloWorldQuery中注册ItemType

public HelloWorldQuery()
{
...
... Field<ItemType>(
"item",
resolve: context =>
{
return new Item {
Barcode = "123",
Title = "Headphone",
SellingPrice = 12.99M
};
}
);
}

这里我们暂时设置了一个硬编码的返回值。所以当查询item对象的时候,这个硬编码的返回值会输出出来。

现在我们启动项目,进入GraphiQL界面

首先我们设置查询为

query {
item{
barcode
sellingPrice
}
}

运行查询之后,结果是

{
"data": {
"item": {
"barcode": "123",
"sellingPrice": 12.99
}
}
}

然后我们修改查询为

query {
item{
barcode
sellingPrice
title
}
}

运行查询之后,结果是

{
"data": {
"item": {
"barcode": "123",
"sellingPrice": 12.99,
"title": "Headphone"
}
}
}

这说明我们的GraphQL查询已经生效,api根据我们需要的字段返回了正确的返回值。

参数

这里我们可以使用参数去除前面的硬编码。

为了说明如何使用参数,这里我们首先创建一个数据源类DataSource, 其代码如下

public class DataSource
{
public IList<Item> Items
{
get;
set;
} public DataSource()
{
Items = new List<Item>(){
new Item { Barcode= "123", Title="Headphone", SellingPrice=50},
new Item { Barcode= "456", Title="Keyboard", SellingPrice= 40},
new Item { Barcode= "789", Title="Monitor", SellingPrice= 100}
};
} public Item GetItemByBarcode(string barcode)
{
return Items.First(i => i.Barcode.Equals(barcode));
}
}

这里除了Items集合,我们还添加了一个方法GetItemByBarcode, 这个方法可以根据传递的barcode参数返回第一个匹配的Item

然后现在我们来修改之前的item查询, 添加一个arguments参数, 其代码如下:

Field<ItemType>(
"item",
arguments: new QueryArguments(new QueryArgument<StringGraphType> { Name = "barcode" }),
resolve: context =>
{
var barcode = context.GetArgument<string>("barcode");
return new DataSource().GetItemByBarcode(barcode);
}
);

arguments是一个参数列表,里面可以包含必填参数和选填参数。针对每个参数,我们都需要指定它对应的类型,这里Name属性是设置了当前参数的名称。

resolve参数中, 你可以使用context.GetArgument()方法获取查询中传递的参数值。

现在我们重新启动项目,并在GraphiQL中添加如下查询

query {
item (barcode: "123") {
title
sellingPrice
}
}

输出的查询结果

{
"data": {
"item": {
"title": "Headphone",
"sellingPrice": 50
}
}
}

这个结果与我们预想的一样。

但是这时候如果我们不传递barcode参数

query {
item {
title
sellingPrice
}
}

程序就会报错

{
"data": {
"item": null
},
"errors": [
{
"message": "Error trying to resolve item.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"item"
],
"extensions": {
"code": "INVALID_OPERATION"
}
}
]
}

原因是当前barcode是一个可空项,程序查询时, First方法会报错。所以这时候我们可以使用NonNullGraphType来设置barcode为一个必填项。

QueryArgument<NonNullGraphType<StringGraphType>> { Name = "barcode" }

这样重新启动项目后,继续使用之前报错的查询,GraphiQL就会给出校验错误。

变量

现在是时候将参数变成动态了。 我们不希望每次在查询中写死查询条件,我们希望这个查询参数是动态的,这时候我们就需要使用到变量。

首先,这里我们需要确保我们的GraphQL中间件可以接受参数,所以我们需要在GraphQLRequest类中添加一个参数变量

public class GraphQLRequest
{
public string Query { get; set; }
public JObject Variables { get; set; }
}

然后我们需要修改GraphQLMiddleware中间件的InvokeAsync方法, 在其中添加一行代码设置doc.Inputs

var result = await _executor.ExecuteAsync(doc =>
{
doc.Schema = _schema;
doc.Query = request.Query; doc.Inputs = request.Variables.ToInputs(); }).ConfigureAwait(false);

现在我们的item查询已经支持动态参数了,我们可以运行程序,在GraphiQL中设置如下查询

query($barcode: String!){
item(barcode: $barcode){
title
sellingPrice
}
}

查询中变量是以$开头的, 后面需要加上变量类型,因为之前我们这是了barcode参数为必填项,所以$barcode变量我们也要设置成必填。变量的必填设置是在变量类型后添加一个!号。

最后,在GraphiQL中,你可以使用QUERY VARIABLES面板中输入参数的值。如下图所示,最终结果正确的返回了。

本文源代码:https://github.com/lamondlu/GraphQL_Blogs/tree/master/Part%20V

ASP.NET Core中使用GraphQL - 第五章 字段, 参数, 变量的更多相关文章

  1. ASP.NET Core中使用GraphQL - 第六章 使用EF Core作为持久化仓储

    ASP.NET Core中使用GraphQL ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间件 ASP ...

  2. ASP.NET Core中使用GraphQL - 第七章 Mutation

    ASP.NET Core中使用GraphQL - 目录 ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间 ...

  3. ASP.NET Core中使用GraphQL - 第四章 GraphiQL

    ASP.NET Core中使用GraphQL ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间件 ASP ...

  4. ASP.NET Core中使用GraphQL - 第三章 依赖注入

    ASP.NET Core中使用GraphQL ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间件 SOL ...

  5. ASP.NET Core 中文文档 第五章 测试(5.2)集成测试

    原文: Integration Testing 作者: Steve Smith 翻译: 王健 校对: 孟帅洋(书缘) 集成测试确保应用程序的组件组装在一起时正常工作. ASP.NET Core支持使用 ...

  6. ASP.NET Core中使用GraphQL - 最终章 Data Loader

    ASP.NET Core中使用GraphQL - 目录 ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间 ...

  7. ASP.NET Core中使用GraphQL - 第八章 在GraphQL中处理一对多关系

    ASP.NET Core中使用GraphQL - 目录 ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间 ...

  8. ASP.NET Core中使用GraphQL - 第九章 在GraphQL中处理多对多关系

    ASP.NET Core中使用GraphQL ASP.NET Core中使用GraphQL - 第一章 Hello World ASP.NET Core中使用GraphQL - 第二章 中间件 ASP ...

  9. ASP.NET Core中使用GraphQL - 第一章 Hello World

    前言 你是否已经厌倦了REST风格的API? 让我们来聊一下GraphQL. GraphQL提供了一种声明式的方式从服务器拉取数据.你可以从GraphQL官网中了解到GraphQL的所有优点.在这一系 ...

随机推荐

  1. Python爬虫-pyspider框架的使用

      pyspider 是一个用python实现的功能强大的网络爬虫系统,能在浏览器界面上进行脚本的编写,功能的调度和爬取结果的实时查看,后端使用常用的数据库进行爬取结果的存储,还能定时设置任务与任务优 ...

  2. Windows 下python 环境安装

    1.先在官网上下载安装包,官网地址:  https://www.python.org   2. 选择自己需要的版本进行安装,最好选择新版本下载,   3. 下载完成后,双击运行安装,一直next,直至 ...

  3. 【prufer编码】BZOJ1430 小猴打架

    Description 一开始森林里面有N只互不相识的小猴子,它们经常打架,但打架的双方都必须不是好朋友.每次打完架后,打架的双方以及它们的好朋友就会互相认识,成为好朋友.经过N-1次打架之后,整个森 ...

  4. BZOJ_1132_[POI2008]Tro_计算几何

    BZOJ_1132_[POI2008]Tro_计算几何 Description 平面上有N个点. 求出所有以这N个点为顶点的三角形的面积和 N<=3000 Input 第一行给出数字N,N在[3 ...

  5. jdbc 增删改查以及遇见的 数据库报错Can't get hostname for your address如何解决

    最近开始复习以前学过的JDBC今天肝了一晚上 来睡睡回笼觉,长话短说 我们现在开始. 我们先写一个获取数据库连接的jdbc封装类 以后可以用 如果不是maven环境的话在src文件下新建一个db.pr ...

  6. mysql输入中文出现ERROR 1366

    MySQL输入中文出现如下错误: ERROR 1366: 1366: Incorrect string value: '\xE6\xB0\xB4\xE7\x94\xB5...' for column ...

  7. r.js合并实践 --项目中用到require.js做生产时模块开发 r.js build.js配置详解

    本文所用源代码已上传,需要的朋友自行下载:点我下载 第一步: 全局安装  npm install -g requirejs 第二步: 1.以下例子主要实现功能, 1)引用jq库获取dom中元素文本, ...

  8. [翻译 EF Core in Action 1.9] 掀开EF Core的引擎盖看看EF Core内部是如何工作的

    Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...

  9. 面向对象之三个基本特征(javaScript)

    1. 前言 2. 封装 3. 继承 4. 多态 5. 总结 1. 前言 了解过面向对象的同学应该都知道,面向对象三个基本特征是:封装.继承.多态,但是对于这三个词具体可能不太了解. 2. 封装 在说封 ...

  10. python 生成 1900-2100 的二十四节气文件

    [学习笔记] 转载 #!/usr/bin/python3.7# -*- coding:utf-8 -*- '''整体思路1:根据公式算出节气日期 1900 年到 2100  200 年的时间2:特殊的 ...