zoukankan      html  css  js  c++  java
  • ASP.NET Core中使用GraphQL

    中间件#

    如果你熟悉ASP.NET Core的中间件,你可能会注意到之前的博客中我们已经使用了一个中间件,

    Copy
    app.Run(async (context) =>
    {
        var result = await new DocumentExecuter()
            .ExecuteAsync(doc =>
            {
                doc.Schema = schema;
                doc.Query = @"
                    query {
                        hello
                    }
                ";
            }).ConfigureAwait(false);
    
        var json = new DocumentWriter(indent: true)
            .Write(result)
        await context.Response.WriteAsync(json);
    });

    这个中间件负责输出了当前查询的结果。

    中间件的定义:

    中间件是装载在应用程序管道中的组件,负责处理请求和响应,每一个中间件

    • 可以选择是否传递请求到应用程序管道中的下一个组件
    • 可以在应用程序管道中下一个组件运行前和运行后进行一些操作

    来源: Microsoft Documentation

    实际上中间件是一个委托,或者更精确的说是一个请求委托(Request Delegate)。 正如他的名字一样,中间件会处理请求,并决定是否将他委托到应用程序管道中的下一个中间件中。在我们前面的例子中,我们使用IApplicationBuilder类的Run()方法配置了一个请求委托。

    使用动态查询体替换硬编码查询体#

    在我们之前的例子中,中间件中的代码非常简单,它仅是返回了一个固定查询的结果。然而在现实场景中,查询应该是动态的,因此我们必须从请求中读取查询体。

    在服务器端,每一个请求委托都可以接受一个HttpContext参数。如果一个查询体是通过POST请求发送到服务器的,你可以很容易的使用如下代码获取到请求体中的内容。

    Copy
    string body;  
    using (var streamReader = new StreamReader(httpContext.Request.Body))  
    {
        body = await streamReader.ReadToEndAsync();
    }

    在获取请求体内容之前,为了不引起任何问题,我们需要先检测一些当前请求

    • 是否是一个POST请求
    • 是否使用了特定的Url, 例如 /api/graphql

    因此我们需要对代码进行调整。

    Copy
    if(context.Request.Path.StartsWithSegments("/api/graphql") 
       && string.Equals(context.Request.Method, 
                        "POST", 
                        StringComparison.OrdinalIgnoreCase))  
    {
        string body;
        using (var streamReader = new StreamReader(context.Request.Body))
        {
            body = await streamReader.ReadToEndAsync();
        }
    
    ....
    ....
    ....

    一个请求体可以包含很多字段,这里我们约定传入graphql查询体字段名称是query。因此我们可以将请求体中的JSON字符串转换成一个包含Query属性的复杂类型。

    这个复杂类型代码如下:

    Copy
    public class GraphQLRequest
    {
        public string Query { get; set; }
    }

    下一步我们要做的就是,反序列化当前请求体的内容为一个GraphQLRequest类型的实例。这里我们需要使用Json.Net中的静态方法JsonConvert.DeserializeObjct来替换之前的硬编码的查询体。

    Copy
    var request = JsonConvert.DeserializeObject<GraphQLRequest>(body);
    
    var result = await new DocumentExecuter().ExecuteAsync(doc =>
    {
        doc.Schema = schema;
        doc.Query = request.Query;
    }).ConfigureAwait(false);

    在完成以上修改之后,Startup.cs文件的Run方法应该是这个样子的。

    Copy
    app.Run(async (context) =>
    {
        if (context.Request.Path.StartsWithSegments("/api/graphql")
            && string.Equals(context.Request.Method, 
                             "POST", 
                             StringComparison.OrdinalIgnoreCase))
        {
            string body;
            using (var streamReader = new StreamReader(context.Request.Body))
            {
                body = await streamReader.ReadToEndAsync();
    
                var request = JsonConvert.DeserializeObject<GraphQLRequest>(body);
                var schema = new Schema { Query = new HelloWorldQuery() };
    
                var result = await new DocumentExecuter()
                    .ExecuteAsync(doc =>
                {
                    doc.Schema = schema;
                    doc.Query = request.Query;
                }).ConfigureAwait(false);
    
                var json = new DocumentWriter(indent: true)
                    .Write(result);
                await context.Response.WriteAsync(json);
            }
        }
    });

    最终效果#

    现在我们可以使用POSTMAN来创建一个POST请求, 请求结果如下:

    结果正确返回了。

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

     
  • 相关阅读:
    Unrecognized attribute 'targetFramework'.错误解决
    [译]Razor内幕之模板
    [译]Razor内幕之解析
    Java下载中文乱码问题解决方法
    获取矩形中心点与矩形外某点连线和矩形交点的算法
    做产品开发的感想
    [译]Razor内幕之表达式
    Could not find the main class. Program will exit.
    基于SAML的单点登录.NET代理端实现方案
    Linux内核虚拟内存的管理结构说明
  • 原文地址:https://www.cnblogs.com/lhxsoft/p/11903527.html
Copyright © 2011-2022 走看看