代码之家  ›  专栏  ›  技术社区  ›  gvdm

找不到名为“x”的带有信号器的客户端方法

  •  1
  • gvdm  · 技术社区  · 6 年前

    我有一个ASP.NET样板文件v3.6.2项目(.net core/angular),其中我需要从后端方法调用客户端函数,因此我使用 ASP.NET Core SignalR implementation .

    我遵循官方文件,因此:

    在后端

    1. 在我的模块中,我将依赖项添加到 AbpAspNetCoreSignalRModule 以下内容:

      [DependsOn(typeof(AbpAspNetCoreSignalRModule))]
      public class MyModule : AbpModule
      

      并添加了 this 模块项目的nuget包。

    2. 然后我把 AbpCommonHub 类以利用信号器集线器的内置实现,添加 SendMessage() 用于发送消息的方法:

      public interface IMySignalRHub :  ITransientDependency
      {
          Task SendMessage(string message);
      }
      
      public class MySignalRHub: AbpCommonHub, IMySignalRHub {
          protected IHubContext<MySignalRHub> _context;
          protected IOnlineClientManager onlineClientManager;
          protected IClientInfoProvider clientInfoProvider;
      
          public MySignalRHub(
              IHubContext<MySignalRHub> context, 
              IOnlineClientManager onlineClientManager,
              IClientInfoProvider clientInfoProvider)
          : base(onlineClientManager, clientInfoProvider) {
              AbpSession = NullAbpSession.Instance;
              _context = context;
          }
      
          public async Task SendMessage(string message) {
              await _context.Clients.All.SendAsync("getMessage", string.Format("User {0}: {1}", AbpSession.UserId, message));
          }
      }
      
    3. 我将'/signal'URL的映射更改为 MySignalRHub 以下内容:

      public class Startup {
          public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {
              [...]
              # if FEATURE_SIGNALR
                  app.UseAppBuilder(ConfigureOwinServices);
              # elif FEATURE_SIGNALR_ASPNETCORE
                  app.UseSignalR(routes => {
                      routes.MapHub<MySignalRHub>("/signalr");
                  });
              # endif
              [...]
          }
      }
      
    4. 然后,我使用集线器在服务实现中发送消息:

      public class MyAppService: AsyncCrudAppService<MyEntity, MyDto, int, PagedAndSortedResultRequestDto, MyCreateDto, MyDto>, IMyAppService {
      
          private readonly IMySignalRHub _hub;
      
          public MyAppService(IRepository<MyEntity> repository, IMySignalRHub hub) : base(repository) {
              _hub = hub;
          }
      
          public override Task<MyDto> Create(MyCreateDto input) {
              _hub.SendMessage("test string").Wait();
              [...]
          }
      }
      

    在客户机中

    所有配置和包含已从原始模板就位。当我打开Angular应用程序时,我可以看到这个控制台日志:

    DEBUG: Connected to SignalR server!
    DEBUG: Registered to the SignalR server!
    

    当我尝试调用将消息发送到客户机的后端服务时,我在控制台中收到以下警告:

    Warning: No client method with the name 'getMessage' found.
    

    我尝试了很多解决方案 official documentation 在互联网上,但没有一个是有效的。我无法在客户端代码中定义“GetMessage”处理程序。

    一些 非工作 我尝试的例子:

    实施1:

    // This point is reached
    abp.event.on('getMessage', userNotification => {
        debugger; // Never reaches this point
    });
    

    实施2:

    // This point is reached
    abp.event.on('abp.notifications.received', userNotification => {
        debugger; // Never reaches this point
    });
    

    实施3:

    // This is taken from the official documentation and triggers the error:
    // ERROR TypeError: abp.signalr.startConnection is not a function
    abp.signalr.startConnection('/signalr', function (connection) {
        connection.on('getMessage', function (message) {
            console.log('received message: ' + message);
        });
    });
    

    你有没有发现自己处于这种情况?在Angular客户机中,您有处理程序定义的简单工作示例吗?

    更新

    我尝试了这个替代解决方案,改变了 SignalRAspNetCoreHelper 类(基本模板附带的共享类):

    export class SignalRAspNetCoreHelper {
        static initSignalR(): void {
    
            var encryptedAuthToken = new UtilsService().getCookieValue(AppConsts.authorization.encrptedAuthTokenName);
    
            abp.signalr = {
                autoConnect: true,
                connect: undefined,
                hubs: undefined,
                qs: AppConsts.authorization.encrptedAuthTokenName + "=" + encodeURIComponent(encryptedAuthToken),
                remoteServiceBaseUrl: AppConsts.remoteServiceBaseUrl,
                startConnection: undefined,
                url: '/signalr'
            };
    
            jQuery.getScript(AppConsts.appBaseUrl + '/assets/abp/abp.signalr-client.js', () => {
                // ADDED THIS
                abp.signalr.startConnection(abp.signalr.url, function (connection) {
                    connection.on('getMessage', function (message) { // Register for incoming messages
                        console.log('received message: ' + message);
                    });
                });
            });
        }
    }
    

    现在在控制台中,我可以看到这两条消息:

    Warning: No client method with the name 'getMessage' found.
    SignalRAspNetCoreHelper.ts:22 received message: User 2: asd
    

    所以这是有效的,但不是完全有效。“getmessage”处理程序不可见。 使用ASP.NET样板文件以角度实现消息处理程序的正确方法是什么?

    3 回复  |  直到 5 年前
        1
  •  2
  •   aaron    6 年前

    autoConnect: false

    abp.signalr = {
        autoConnect: false,
        // ...
    };
    

    AbpCommonHub IRealTimeNotifier SignalRRealTimeNotifier

        2
  •  1
  •   ikos23    6 年前

    Clients.Others.SendAsync Client.AllExcept.SendAsync Clients.All.SendAsync

    connection.on('getMessage',

        3
  •  1
  •   Sibeesh Venu    5 年前
    enter image description here

    public async getWorkSheetById(worksheetId: string): Promise < Worksheet > {
        const worksheet: Worksheet = await this._worksheetService.getWorksheet(worksheetId);
        this.displayWorksheet(worksheet);
        await this._worksheetEventsService.joinWorksheetChannel(this._loadedWorksheet.id);
        return worksheet;
    }
    

    await this.subscribeToSendMethod(this._loadedWorksheet)

    public subscribeToSendMethod(loadedWorksheet: Worksheet): Worksheet {
        let newWorksheet: Worksheet;
        this._hubConnection.on('Send', (groupId: string, payloadType: string, payload: string, senderUserId: string)=> {
            newWorksheet=this._worksheetHandler.handlePayload(payloadType, payload, loadedWorksheet);
            this.displayWorksheet(newWorksheet);
        }
        );
        return newWorksheet;
    }