.net 核心 GraphQL、GraphQL.SystemTextJson:不支持“System.Type”实例的序列化和反序列化

如何解决.net 核心 GraphQL、GraphQL.SystemTextJson:不支持“System.Type”实例的序列化和反序列化

在 ASP.NET core 5 应用程序中,我将 GraphQL 与 GraphQL.SystemTextJson 一起使用。 当我尝试返回结果时,我收到 System.NotSupportedException,提示“不支持‘System.Type’实例的序列化和反序列化,应避免,因为它们会导致安全问题。”

我怀疑 DocumentWriter 的配置中缺少某些东西。

在ConfigureServices中是这样配置的:

    public void ConfigureServices(IServiceCollection services)
    {

        services.AddControllers();

        ...

        services.AddScoped<IDocumentWriter,DocumentWriter>();

有什么建议吗?

更新:

为了完整性,正如@AndrewSilver 所要求的,我报告了整个代码(改编自 https://www.red-gate.com/simple-talk/dotnet/net-development/building-and-consuming-graphql-api-in-asp-net-core-3-1/ 并移植到 .net core 5.0)。

    public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {

        services.AddControllers();
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1",new OpenApiInfo { Title = "GraphQlExperiments",Version = "v1" });
        });

        services.AddScoped<IDocumentExecuter,DocumentExecuter>();
        services.AddScoped<IDocumentWriter,DocumentWriter>();
        services.AddScoped<AuthorService>();
        services.AddScoped<AuthorRepository>();
        services.AddScoped<AuthorQuery>();
        services.AddScoped<AuthorType>();
        services.AddScoped<BlogPostType>();
        services.AddScoped<ISchema,GraphQLDemoSchema>();
        services.AddControllers();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app,IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseSwagger();
            app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json","GraphQlExperiments v1"));
        }


        // See: https://github.com/JosephWoodward/graphiql-dotnet
        app.UseGraphiQl("/graphiql","/api/v1/graphql");


        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

public class Author
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class BlogPost
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public Author Author { get; set; }
}

public class AuthorType : ObjectGraphType<Author>
{
    public AuthorType()
    {
        Name = "Author";
        Field(_ => _.Id).Description("Author's Id.");
        Field(_ => _.FirstName).Description("First name of the author");
        Field(_ => _.LastName).Description("Last name of the author");
    }
}

public class BlogPostType : ObjectGraphType<BlogPost>
{
    public BlogPostType()
    {
        Name = "BlogPost";
        Field(_ => _.Id,type:
        typeof(IdGraphType)).Description("The Id of the Blog post.");
        Field(_ => _.Title).Description("The title of the blog post.");
        Field(_ => _.Content).Description("The content of the blog post.");
    }
}

public class AuthorQuery : ObjectGraphType
{
    public AuthorQuery(AuthorService authorService)
    {
        int id = 0;
        Field<ListGraphType<AuthorType>>(
            name: "authors",resolve: context =>
            {
                return authorService.GetAllAuthors();
            });
        Field<AuthorType>(
            name: "author",arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),resolve: context =>
            {
                id = context.GetArgument<int>("id");
                return authorService.GetAuthorById(id);
            }
        );
        Field<ListGraphType<BlogPostType>>(
            name: "blogs",resolve: context =>
            {
                return authorService.GetPostsByAuthor(id);
            }
        );
    }
}

public class GraphQLQueryDTO
{
    public string OperationName { get; set; }
    public string NamedQuery { get; set; }
    public string Query { get; set; }
    public string Variables { get; set; }
}

public class GraphQLDemoSchema : Schema,ISchema
{
    public GraphQLDemoSchema(IServiceProvider resolver) : base(resolver)
    {
        Query = resolver.GetService<AuthorQuery>();
    }
}

public class AuthorService
{
    private readonly AuthorRepository _authorRepository;

    public AuthorService(AuthorRepository
            authorRepository)
    {
        _authorRepository = authorRepository;
    }
    public List<Author> GetAllAuthors()
    {
        return _authorRepository.GetAllAuthors();
    }
    public Author GetAuthorById(int id)
    {
        return _authorRepository.GetAuthorById(id);
    }
    public List<BlogPost> GetPostsByAuthor(int id)
    {
        return _authorRepository.GetPostsByAuthor(id);
    }
}

public class AuthorRepository
{
    private readonly List<Author> authors = new List<Author>();
    private readonly List<BlogPost> posts = new List<BlogPost>();

    public AuthorRepository()
    {
        Author author1 = new Author
        {
            Id = 1,FirstName = "Joydip",LastName = "Kanjilal"
        };
        Author author2 = new Author
        {
            Id = 2,FirstName = "Steve",LastName = "Smith"
        };
        BlogPost csharp = new BlogPost
        {
            Id = 1,Title = "Mastering C#",Content = "This is a series of articles on C#.",Author = author1
        };
        BlogPost java = new BlogPost
        {
            Id = 2,Title = "Mastering Java",Content = "This is a series of articles on Java",Author = author1
        };
        posts.Add(csharp);
        posts.Add(java);
        authors.Add(author1);
        authors.Add(author2);
    }
    public List<Author> GetAllAuthors()
    {
        return this.authors;
    }
    public Author GetAuthorById(int id)
    {
        return authors.Where(author => author.Id == id).FirstOrDefault<Author>();
    }
    public List<BlogPost> GetPostsByAuthor(int id)
    {
        return posts.Where(post => post.Author.Id == id).ToList<BlogPost>();
    }
}

    [Route("/api/v1/graphql")]
public class GraphQLController : Controller
{
    private readonly ISchema _schema;
    private readonly IDocumentExecuter _executer;
    public GraphQLController(
        ISchema schema,IDocumentExecuter executer
        )
    {
        _schema = schema;
        _executer = executer;
    }

    [HttpPost]
    public async Task<IActionResult> Post([FromBody] GraphQLQueryDTO query)
    {
        var result = await _executer.ExecuteAsync(_ =>
        {
            _.Schema = _schema;
            _.Query = query.Query;
            _.Inputs = query.Variables?.ToInputs();
        });
        if (result.Errors?.Count > 0)
        {
            return BadRequest();
        }
        return Ok(result.Data);
    }
}

这是触发错误的示例请求:

query {
  author (id: 1){
    id
    firstName
    lastName
  }
  blogs
    {
      id
      title
      content
    }
}

解决方法

我解决了创建自定义 JsonConverter 的问题:

public class CustomJsonConverterForType : JsonConverter<Type>
{
    public override Type Read(
        ref Utf8JsonReader reader,Type typeToConvert,JsonSerializerOptions options
        )
    {
        // Caution: Deserialization of type instances like this 
        // is not recommended and should be avoided
        // since it can lead to potential security issues.

        // If you really want this supported (for instance if the JSON input is trusted):
        // string assemblyQualifiedName = reader.GetString();
        // return Type.GetType(assemblyQualifiedName);
        throw new NotSupportedException();
    }

    public override void Write(
        Utf8JsonWriter writer,Type value,JsonSerializerOptions options
        )
    {
        string assemblyQualifiedName = value.AssemblyQualifiedName;
        // Use this with caution,since you are disclosing type information.
        writer.WriteStringValue(assemblyQualifiedName);
    }
}

然后,在 configureServices 中:

        services.AddControllers()
            .AddJsonOptions(options =>
            {
                options.JsonSerializerOptions.WriteIndented = true;
                options.JsonSerializerOptions.Converters.Add(new CustomJsonConverterForType());
            });
,

我使用文档中显示的代码段修复了该问题:https://graphql-dotnet.github.io/docs/migrations/migration3

[HttpPost]
public async Task<IActionResult> Post([FromBody] GraphQLQueryDTO query)
{
  var result = await _executer.ExecuteAsync(_ =>
  {
     _.Schema = _schema;
     _.Query = query.Query;
     _.Inputs = query.Variables?.ToInputs();
  });

  /* ----------- Added this ---------------------------------*/
  HttpContext.Response.ContentType = "application/json";
  HttpContext.Response.StatusCode = 200; // OK
  var writer = new GraphQL.SystemTextJson.DocumentWriter();
  await writer.WriteAsync(HttpContext.Response.Body,result);*
  /* ------------------------------------------------------*/

  if (result.Errors?.Count > 0)
  {
    return BadRequest();
  }
    return Ok(result.Data);
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res