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