Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET Core 3.1信号器:未调用方法_C#_Mongodb_Asp.net Core_Signalr_Auth0 - Fatal编程技术网

C# ASP.NET Core 3.1信号器:未调用方法

C# ASP.NET Core 3.1信号器:未调用方法,c#,mongodb,asp.net-core,signalr,auth0,C#,Mongodb,Asp.net Core,Signalr,Auth0,我有一个应用程序,前端是React,后端是nodejs。我已决定使用Signal重写ASP.NET Core 3.1中的后端。我对ASP.NET Core 3.1和SignalR都是新手,因此我很难确定问题的原因 问题是我从前端调用的hub方法没有被命中。我在几天前遵循了这一点,并设法调用了hub方法,但由于引入了一些特性,例如JWT身份验证和MongoDB,现在没有调用该方法。我不明白为什么 考虑到浏览器中的日志输出,连接似乎成功 我的startup.cs如下所示: namespace MpA

我有一个应用程序,前端是React,后端是nodejs。我已决定使用Signal重写ASP.NET Core 3.1中的后端。我对ASP.NET Core 3.1和SignalR都是新手,因此我很难确定问题的原因

问题是我从前端调用的hub方法没有被命中。我在几天前遵循了这一点,并设法调用了hub方法,但由于引入了一些特性,例如JWT身份验证和MongoDB,现在没有调用该方法。我不明白为什么

考虑到浏览器中的日志输出,连接似乎成功

我的
startup.cs
如下所示:

namespace MpApp.API
{
  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.AddCors(options =>
      {
        options.AddPolicy("AllowSpecificOrigin",
          builder =>
          {
            builder
              .WithOrigins("http://localhost:3000", "http://localhost:3010")
              .AllowAnyMethod()
              .AllowAnyHeader()
              .AllowCredentials();
          });
      });

      var domain = $"https://{Configuration["Auth0:Domain"]}/";
      services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
          options.Authority = domain;
          options.Audience = Configuration["Auth0:Audience"];

          options.Events = new JwtBearerEvents
          {
            OnMessageReceived = context =>
            {
              var accessToken = context.Request.Query["access_token"];

              // If the request is for our hub...
              var path = context.HttpContext.Request.Path;
              if (!string.IsNullOrEmpty(accessToken) &&
                  (path.StartsWithSegments("/chathub")))
              {
                // Read the token out of the query string
                context.Token = accessToken;
              }

              return Task.CompletedTask;
            }
          };
        });

      services.AddAuthorization(options =>
      {
        options.AddPolicy("read:messages",
          policy => policy.Requirements.Add(new HasScopeRequirement("read:messages", domain)));
      });

      services.AddControllers();

      services.AddSignalR();

      // Register the scope authorization handler
      services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();

      Debug.WriteLine("===== about to init config =====");
      services.Configure<DatabaseSettings>(
        Configuration.GetSection(nameof(DatabaseSettings)));

      services.AddSingleton<IDatabaseSettings>(sp =>
        sp.GetRequiredService<IOptions<DatabaseSettings>>().Value);

      services.AddSingleton<IBaseService, BaseService>();

      services.AddSingleton<CollectionService<Profile>>();
      services.AddSingleton<CollectionService<User>>();
    }

    // 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();
      }
      else
      {
        app.UseHsts();
      }

      app.UseHttpsRedirection();

      app.UseRouting();

      app.UseCors("AllowSpecificOrigin");

      app.UseAuthentication();
      app.UseAuthorization();

      app.UseEndpoints(endpoints =>
      {
        endpoints.MapControllers();
        endpoints.MapHub<ChatHub>("/chathub");
      });
    }
  }
}

namespace MyApp.API.Hubs
{
  public class ChatHub : Hub
  {
    protected CollectionService<Profile> _profileService;
    protected CollectionService<User> _userService;

    public ChatHub(CollectionService<Profile> profileService, CollectionService<User> userService)
    {
     // This constructor is being called
      _profileService = profileService;
      _userService = userService;
    }

    [Authorize]
    public async Task UpdateProfile()
    {
      // I have put a breakpoint here but it is not being hit
      await Clients.All.SendAsync("Test");
    }
  }
}
useEffect(() => {
  (async () => {
    if (isAuthenticated) {
      const accessToken = await getAccessTokenSilently();

      const connection = new signalR.HubConnectionBuilder()
        .configureLogging(signalR.LogLevel.Debug)
        .withUrl('http://localhost:3010/chathub', {accessTokenFactory: () => accessToken})
        .build();

      await connection.start();
      setConnected(true);
    }
    // eslint-disable-next-line
  })()
}, [isAuthenticated]);

useEffect(() => {
  (async () => {
    if(connected && user) {
      // this code is being hit, but the method on the back end is not
      await connection?.send('UpdateProfile');
    }
  })()
}, [connected, user])
React前端似乎在等待正确的连接,以及正确调用方法,但它不工作

来自React提供程序的相关代码如下所示:

namespace MpApp.API
{
  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.AddCors(options =>
      {
        options.AddPolicy("AllowSpecificOrigin",
          builder =>
          {
            builder
              .WithOrigins("http://localhost:3000", "http://localhost:3010")
              .AllowAnyMethod()
              .AllowAnyHeader()
              .AllowCredentials();
          });
      });

      var domain = $"https://{Configuration["Auth0:Domain"]}/";
      services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
          options.Authority = domain;
          options.Audience = Configuration["Auth0:Audience"];

          options.Events = new JwtBearerEvents
          {
            OnMessageReceived = context =>
            {
              var accessToken = context.Request.Query["access_token"];

              // If the request is for our hub...
              var path = context.HttpContext.Request.Path;
              if (!string.IsNullOrEmpty(accessToken) &&
                  (path.StartsWithSegments("/chathub")))
              {
                // Read the token out of the query string
                context.Token = accessToken;
              }

              return Task.CompletedTask;
            }
          };
        });

      services.AddAuthorization(options =>
      {
        options.AddPolicy("read:messages",
          policy => policy.Requirements.Add(new HasScopeRequirement("read:messages", domain)));
      });

      services.AddControllers();

      services.AddSignalR();

      // Register the scope authorization handler
      services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();

      Debug.WriteLine("===== about to init config =====");
      services.Configure<DatabaseSettings>(
        Configuration.GetSection(nameof(DatabaseSettings)));

      services.AddSingleton<IDatabaseSettings>(sp =>
        sp.GetRequiredService<IOptions<DatabaseSettings>>().Value);

      services.AddSingleton<IBaseService, BaseService>();

      services.AddSingleton<CollectionService<Profile>>();
      services.AddSingleton<CollectionService<User>>();
    }

    // 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();
      }
      else
      {
        app.UseHsts();
      }

      app.UseHttpsRedirection();

      app.UseRouting();

      app.UseCors("AllowSpecificOrigin");

      app.UseAuthentication();
      app.UseAuthorization();

      app.UseEndpoints(endpoints =>
      {
        endpoints.MapControllers();
        endpoints.MapHub<ChatHub>("/chathub");
      });
    }
  }
}

namespace MyApp.API.Hubs
{
  public class ChatHub : Hub
  {
    protected CollectionService<Profile> _profileService;
    protected CollectionService<User> _userService;

    public ChatHub(CollectionService<Profile> profileService, CollectionService<User> userService)
    {
     // This constructor is being called
      _profileService = profileService;
      _userService = userService;
    }

    [Authorize]
    public async Task UpdateProfile()
    {
      // I have put a breakpoint here but it is not being hit
      await Clients.All.SendAsync("Test");
    }
  }
}
useEffect(() => {
  (async () => {
    if (isAuthenticated) {
      const accessToken = await getAccessTokenSilently();

      const connection = new signalR.HubConnectionBuilder()
        .configureLogging(signalR.LogLevel.Debug)
        .withUrl('http://localhost:3010/chathub', {accessTokenFactory: () => accessToken})
        .build();

      await connection.start();
      setConnected(true);
    }
    // eslint-disable-next-line
  })()
}, [isAuthenticated]);

useEffect(() => {
  (async () => {
    if(connected && user) {
      // this code is being hit, but the method on the back end is not
      await connection?.send('UpdateProfile');
    }
  })()
}, [connected, user])

有人知道为什么会这样吗?我在调用中尝试了一个小写的方法名,但这没有帮助。

[Authorize]
属性放在
ChatHub
类的顶部。如果启动时未配置任何默认授权方案,则需要包含如下授权方案

    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    public class ChatHub: Hub 
    {
          //...
    }
    var resultString = JsonConvert.SerializeObject(ResultObject, new 
    JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            });
    Clients.Caller.SendAsync("ClientFunction", resultString  );
*注意:当我使用SignalR时,我将DTO转换为JSON字符串并将其传递给服务器,可能需要为具有参数的函数执行此操作。 像这样:

     public void FunctionName(string  dtoString)
     {
        
        var dto = JsonConvert.DeserializeObject<MyObjectDto>(dtoString);
        //Do something with my DTO
        
      }
信号器中的令牌是在查询中发送的,所以您需要从查询中读取它们并将它们放在头上

  services.AddAuthentication()
        .AddJwtBearer(options =>
        {
            options.RequireHttpsMetadata = false;
            options.SaveToken = true;
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateAudience = false,
                ValidIssuer = [Issuer Site],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes([YOUR SECRET KEY STRING]))
            };
            options.Events = new JwtBearerEvents
            {
                OnMessageReceived = context =>
                {
                    var path = context.Request.Path;
                    var accessToken = context.Request.Query["access_token"];
                    if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/chathub"))
                    {
                        
                        context.Request.Headers.Add("Authorization", new[] { $"Bearer {accessToken}" });
                    }
                    return Task.CompletedTask;
                }
            };
        });
如果你有任何问题,请告诉我。
希望它能起作用

错误消息是什么?您确定已正确获取令牌吗?