ASP.NET Core中使用GraphQLhtml
咱们已经很好的理解了GraphQL中的字段。在以前HelloWorldQuery
的例子中,咱们添加了2个字段hello
和howdy
. 它们都是标量字段。正如GraphQL官网文档中声明的那样git
"At its simplest, GraphQL is about asking for specific fields on objects"github
简单来讲,GraphQL就是询问对象中的一些特定字段数据库
来源: graphql.orgjson
下面咱们来为咱们的实例程序添加一些复杂的类型。好比,如今咱们须要编写一个库存系统,咱们首先添加一个货物类Item
, 其代码以下:c#
public class Item { public string Barcode { get; set; } public string Title { get; set; } public decimal SellingPrice { get; set; } }
可是咱们不但愿直接针对这个对象建立查询,由于它不是一个GraphQL
对象,它没有继承自ObjectGraphType
, 为了建立一个GraphQL
查询,咱们须要建立一个新类ItemType
, 它继承自ObjectGraphType
类。api
另外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之间的转换的映射。3d
下一步,咱们须要在HelloWorldQuery
中注册ItemType
。code
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