ASP.NET Core中使用GraphQL - 第五章 字段, 參數, 變量


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM