【问题标题】:Subscriptions in GraphQL .NET Core doesn't send response to clientGraphQL .NET Core 中的订阅不会向客户端发送响应
【发布时间】:2021-01-20 20:38:41
【问题描述】:

我正在构建一个 在 Asp Net Core 3.1 中的 GraphQL API。我正在尝试添加一个 subscription,以便在添加新实体时将其发送给订阅者。 当我从 /ui/playground 执行订阅时,与服务器的握手似乎成功了:

GraphQL http 请求 websocket:

当我执行添加评论的突变时,它成功并在数据库上创建了一条记录,但上面的屏幕仍然保持原样,没有更新,也没有从套接字接收到数据。

这是突变:

Field<ReviewType>(
    "createReview",
    arguments: new QueryArguments(
        new QueryArgument<NonNullGraphType<ReviewInput>> 
        { 
            Name = "reviewInput"
        }
    ),
    resolve: context =>
    {
        var review = context.GetArgument<Review>("reviewInput");
        var rev = reviewService.Add(review);
        return rev;
    }
);

ShopSubscition.cs

public partial class ShopSubscription : ObjectGraphType
{
    private readonly IReviewService _reviewService;

    public ShopSubscription(IReviewService reviewService)
    {
        _reviewService = reviewService;
        AddField(new EventStreamFieldType
        {
            Name = "reviewAdded",
            Type = typeof(ReviewType),
            Resolver = new FuncFieldResolver<Review>((context) => context.Source as Review),
            Subscriber = new EventStreamResolver<Review>((context) => _reviewService.ReviewAdded())
        });
    }
}

ReviewService.cs

public class ReviewService : IReviewService
{
    private readonly IReviewRepository _reviewRepository;
    private readonly ISubject<Review> _sub = new ReplaySubject<Review>(1);

    public ReviewService(IReviewRepository reviewRepository)
    {
        _reviewRepository = reviewRepository;
    }

    public Review Add(Review review)
    {
        var addedEntity = _reviewRepository.Add(review);
        _sub.OnNext(review);
        return review;
    }

    public IObservable<Review> ReviewAdded()
    {
        return _sub.AsObservable();
    }
}

我也发布了 Startup.cs,也许它会有所帮助。

Startup.cs

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

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors();

        services.AddDbContext<ShopDbContext>(opt =>
            opt.UseSqlServer(Configuration.GetConnectionString("Default")));

        services.AddScoped<ISupplierRepository, SupplierRepository>();
        services.AddScoped<IProductRepository, ProductRepository>();
        services.AddScoped<IReviewRepository, ReviewRepository>();

        services.AddScoped<IReviewService, ReviewService>();

        services.AddSingleton<IDataLoaderContextAccessor, DataLoaderContextAccessor>();
        services.AddSingleton<DataLoaderDocumentListener>();

        services.AddScoped<ShopSchema>();
        services.AddGraphQL(options =>
        {
            options.EnableMetrics = false;
        })
            .AddWebSockets()
            .AddSystemTextJson()
            .AddGraphTypes(typeof(ShopSchema), ServiceLifetime.Scoped).AddDataLoader();

        services.AddControllers()
            .AddNewtonsoftJson(o => o.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ShopDbContext dbContext)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseCors("Cors");
        app.UseHttpsRedirection();
        app.UseRouting();
        app.UseAuthorization();
        app.UseWebSockets();
        app.UseGraphQLWebSockets<ShopSchema>("/graphql");

        app.UseGraphQL<ShopSchema>();
        app.UseGraphQLPlayground(options: new GraphQLPlaygroundOptions { GraphQLEndPoint ="/graphql", SchemaPollingEnabled = false });

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

提前感谢您的帮助。

【问题讨论】:

    标签: c# .net graphql graphql.net


    【解决方案1】:

    经过深入调查,我发现了问题所在。我发布了解决方案,也许可以帮助某人。

    问题在于依赖注入:包含订阅“通知逻辑”的类(在我的情况下为 ReviewService.cs)必须注册为 Singleton 而不是 Scoped。这引起了一种连锁反应,将存储库类注册为瞬态。 这是工作代码:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options => options.AddPolicy("Cors",
                builder =>
                {
                    builder.AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader();
                }));
    
            services.AddDbContext<ShopDbContext>(opt =>
                opt.UseSqlServer(Configuration.GetConnectionString("Default")));
    
            services.AddTransient<ISupplierRepository, SupplierRepository>();
            services.AddTransient<IProductRepository, ProductRepository>();
            services.AddTransient<IReviewRepository, ReviewRepository>();
    
            services.AddSingleton<IReviewService, ReviewService>();
    
            services.AddSingleton<IDataLoaderContextAccessor, DataLoaderContextAccessor>();
            services.AddSingleton<DataLoaderDocumentListener>();
    
            services.AddScoped<ShopSchema>();
            services.AddGraphQL(options =>
            {
                options.EnableMetrics = false;  // info sulla richiesta (ms, campi richiesti, ecc)
            })
                .AddWebSockets()
                .AddSystemTextJson()
                .AddGraphTypes(typeof(ShopSchema), ServiceLifetime.Scoped).AddDataLoader();
    
            services.AddControllers()
                .AddNewtonsoftJson(o => o.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-11
      • 2023-04-03
      • 2022-12-12
      • 2023-01-31
      • 2019-07-19
      • 1970-01-01
      • 2013-09-14
      • 1970-01-01
      相关资源
      最近更新 更多