调用服务器中心方法失败

时间:2019-07-08 13:01:51

标签: javascript c# reactjs signalr

我正在尝试使我的React应用程序和用C#编写的服务器组件之间建立基本的signalR连接。

我已经使用JQuery SignalR库引导了signalR客户端并作为中间件调用。在启动时,它应该尝试并调用唯一可用的服务器方法,然后这将导致构建集线器并调用该方法。但是,不会调用集线器的构造函数,也不会调用被调用的方法。根据客户端连接属性,可以很明显地找到集线器并进行连接,因为在调用onStateChanged()方法时将“ Connected”作为新状态,并且可以在chrome dev工具中查看连接对象。但是,调用服务器方法时,它只会在javascript控制台中给我以下错误(服务器进程上什么都没有发生)

  

jquery-1.12.0.min.js:4开机自检   https://localhost:3830/signalr/send?transport=serverSentEvents&clientProtocol=1.5&connectionToken=AQAAANCMnd8BFdERjHoAwE%2FCl%2BsBAAAAuw4b0U8E80ynfN6Njj7iGAAAAAACAAAAAAADZgAAwAAAABAAAAC2F%2BIFF73jLL%2FLtWBjkBafAAAAAASAAACgAAAAEAAAAIKqx8wP6asrIYRF24wgF%2FwwAAAAJLyt3OCdy%2FIXbOYlu1vSNKLkF%2Fs19QM9yVQb%2FhpfVxavZSxG7uauwc3vXSfZYDFrFAAAAMzCxkLJZxDevB1J8Wqst8IUk0Al&connectionData=%5B%7B%22name%22%3A%22logtailhub%22%7D%5D   500(内部服务器错误)

更详细的SignalR错误是

  

错误:发送失败。↵at Object.error   (https://localhost:3830/assets/signalr/jquery.signalR-2.2.0.min.js:8:4512)↵   在Object.transportError   (https://localhost:3830/assets/signalr/jquery.signalR-2.2.0.min.js:8:4627)↵   在s   (https://localhost:3830/assets/signalr/jquery.signalR-2.2.0.min.js:8:18349)↵   在Object.error   (https://localhost:3830/assets/signalr/jquery.signalR-2.2.0.min.js:8:18693)↵   在我   (https://localhost:3830/assets/signalr/jquery-1.12.0.min.js:2:27451)↵   在Object.fireWith [作为rejectWith]   (https://localhost:3830/assets/signalr/jquery-1.12.0.min.js:2:28215)↵   在y   (https://localhost:3830/assets/signalr/jquery-1.12.0.min.js:4:22617)↵   在XMLHttpRequest.c   (https://localhost:3830/assets/signalr/jquery-1.12.0.min.js:4:26750

在下面的代码中,我在行上中断

const sessionHub = connection[HUB_NAME];

然后让我查看该特定集线器的连接,该集线器已连接并且看起来不错。但是在下面的调用行中,它失败并出现上述错误。

我的客户端中间件代码

import hostlookup from "./hostlookup";
import { LOGTAIL_INCOMING_METHOD_UPDATED, HUB_NAME, SIGNALR_CONNECT, SIGNALR_DISCONNECT, LOGTAIL_ACTION_START, LOGTAIL_ACTION_STOP, LOGTAIL_SERVER_METHOD_STOP, LOGTAIL_SERVER_METHOD_START, SIGNALR_STATE_DISCONNECTED, SIGNALR_STATE_CONNECTING, SIGNALR_STATE_RECONNECTING } from "./constants";
import { getSignalRStatusChangedAction, getSignalRStopAction } from "./actions";
import { getLogTailUpdatedAction } from "../../modules/logtail/actions";

const url = hostlookup().host + '/signalr';
const connection = $.hubConnection(url, {
    useDefaultPath: false
});

export default function createSignalrMiddleware() {
    return (store) => {
        const dispatch = store.dispatch.bind(store);

        const SIGNALR_STATES = {
            0: 'Connecting',
            1: 'Connected',
            2: 'Reconnecting',
            4: 'Disconnected'
        };

        let keepAlive = true;
        let wasConnected = false;
        let currentState = null;

        initialiseListeners(dispatch);

        function onStateChanged(state) {
            if (currentState === state) { return; }

            if (currentState === 2 && state === 1) {
                connection.start().done(() => {
                    // reconnect actions if required
                });
            }

            currentState = state;
            dispatch(getSignalRStatusChangedAction(state));
        }

        connection.stateChanged((state) => {
            const newStateName = SIGNALR_STATES[state.newState];

            if (newStateName === 'Connected') {
                wasConnected = true;
            }

            onStateChanged(state.newState);
        });

        connection.disconnected(() => {
            if (keepAlive) {
                if (wasConnected) {
                    onStateChanged(SIGNALR_STATE_RECONNECTING);
                } else {
                    onStateChanged(SIGNALR_STATE_CONNECTING);
                }

                connection.start().done(() => {
                    // Connect actions if required
                });
            }
        });

        function initialiseListeners(dispatcher) {
            const sessionHub = connection[HUB_NAME] = connection.createHubProxy(HUB_NAME);

            sessionHub.on(LOGTAIL_INCOMING_METHOD_UPDATED,
                (logDataLine) => {
                    dispatch(getLogTailUpdatedAction(logDataLine));
                })

            sessionHub.on('Disconnect', () => dispatcher(getSignalRStopAction()));
        }

        return (next) => (action) => {
            const { type } = action;
            const sessionHub = connection[HUB_NAME];

            switch (type) {
                case SIGNALR_CONNECT:
                    keepAlive = true;
                    onStateChanged(SIGNALR_STATE_CONNECTING);
                    connection.start().done(() => {
                        const sessionHub = connection[HUB_NAME];
                        sessionHub.invoke(LOGTAIL_SERVER_METHOD_START, 'test')
                        // Connect actions if required
                    });
                    return;

                case SIGNALR_DISCONNECT:
                    keepAlive = false;
                    wasConnected = false;
                    onStateChanged(SIGNALR_STATE_DISCONNECTED);
                    connection.stop();
                    return;

                case LOGTAIL_ACTION_START:
                    sessionHub.invoke(LOGTAIL_SERVER_METHOD_START, action.applicationName);
                    return;

                case LOGTAIL_ACTION_STOP:
                    sessionHub.invoke(LOGTAIL_SERVER_METHOD_STOP);
                    return;

                default:
                    return next(action);
            }
        }
    }
}

我的服务器中心代码

    public interface ILogTailClient
    {
        void LogDataUpdated(string[] logData);        
    }

    [Authorize]
    public class LogTailHub : Hub<ILogTailClient>
    {
        private readonly IClientConnectionHandler _clientConnectionHandler;
        private readonly IAuthorisedUserCache _userCache;
        private readonly ILogTailService _logTailService;

        public LogTailHub(IClientConnectionHandler clientConnectionHandler, IAuthorisedUserCache userCache, ILogTailService logTailService)
        {
            _clientConnectionHandler = clientConnectionHandler;
            _userCache = userCache;
            _logTailService = logTailService;
        }

        public override Task OnConnected()
        {
            var clientConnection = GetClientConnection();
            if (clientConnection != null)
                _clientConnectionHandler.OnConnected(clientConnection);

            return base.OnConnected();
        }

        public override Task OnReconnected()
        {
            lock (_clientConnectionHandler)
            {
                _clientConnectionHandler.OnDisconnected(Context.ConnectionId);

                var clientConnection = GetClientConnection();
                if (clientConnection != null)
                    _clientConnectionHandler.OnConnected(clientConnection);
            }

            return base.OnReconnected();
        }

        public override async Task OnDisconnected(bool stopCalled)
        {
            _clientConnectionHandler.OnDisconnected(Context.ConnectionId);            
            StopTailing();
            await base.OnDisconnected(stopCalled);
        }

        public void StartTailing(string applicationName)
        {
            _logTailService.StartListening(Context.ConnectionId, applicationName);
        }

        public void StopTailing()
        {
            _logTailService.StopListening(Context.ConnectionId);
        }

        private IClientConnection GetClientConnection()
        {
            if (Context.User != null && _userCache.TryGetUser(Context.User.Identity.Name, out var authorisedUser))
            {
                return new ClientConnection(Context.ConnectionId, authorisedUser);
            }

            return null;
        }
    }

中心的DI注册

public class WebNotificationsModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterAssemblyTypes(GetType().Assembly).AsImplementedInterfaces()
                .Except<LogTailHub>()          // Defined below
                .Except<HubContextProvider>();  // Defined as Singleton below

            var hubConfiguration = new HubConfiguration
            {
                EnableJavaScriptProxies = false,
                EnableDetailedErrors = true
            };
            builder.Register(ctx => hubConfiguration);

            builder.Register(ctx => {
                var connectionManager = hubConfiguration.Resolver.Resolve<IConnectionManager>();
                return connectionManager.GetHubContext<LogTailHub, ILogTailClient>();
            }).ExternallyOwned();

            builder.RegisterType<HubContextProvider>().As<IHubContextProvider>().SingleInstance();

            builder.RegisterType<LogTailHub>().ExternallyOwned(); // SignalR hub registration

            var serializer = new JsonSerializer();
            serializer.Converters.Add(new StringEnumConverter());
            builder.RegisterInstance(serializer).As<JsonSerializer>();
        }
    }

1 个答案:

答案 0 :(得分:0)

SignalR正在调用的服务器端代码引发异常,您需要此异常的详细信息以将代码指向何处。详细信息应在您的服务器事件日志中。另外,您可以(临时)打开详细错误,这会将异常详细信息推送到JavaScript控制台中。

在Startup.cs中:

hubConfiguration.EnableDetailedErrors = true;

https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.signalr.huboptions.enabledetailederrors?view=aspnetcore-2.2

如果您选择这种方法,请确保在部署之前关闭详细的错误。