调用ApiController会导致SignalR停止工作

时间:2017-03-20 23:51:01

标签: c# asp.net signalr azure-web-sites

我有一个监控/日志记录中心,它使用SignalR(2.2.1)和Azure Mobile App进行身份验证。无论ApiController上是否存在MobileAppController属性,即使ApiController不包含集线器调用代码,从浏览器调用/ api / values也会立即杀死我的SignalR集线器。我必须重新启动Web应用程序才能让它再次运行。与此同时,网页将继续尝试连接/重新连接。

条纹控制器看起来像

public class ValuesController : ApiController
{
    // GET api/values
    public string Get()
    {
        return "Hello World!";
    }
}

我在

中设置了WebApi
    public static void ConfigureMobileApp(IAppBuilder app, IDependencyResolver resolver)
    {
        HttpConfiguration config = new HttpConfiguration();
        config.DependencyResolver = resolver;
        config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
        config.Formatters.Add(new BsonMediaTypeFormatter());

        new MobileAppConfiguration()
            //.MapApiControllers()
            .AddTables(
                new MobileAppTableConfiguration()
                    .MapTableControllers()
                    .AddEntityFramework()
            )
            .AddPushNotifications()
            .MapLegacyCrossDomainController()
            .ApplyTo(config);

        // Use Entity Framework Code First to create database tables based on your DbContext
        Database.SetInitializer(new MobileServiceInitializer());

        MobileAppSettingsDictionary settings = config.GetMobileAppSettingsProvider().GetMobileAppSettings();

        if (string.IsNullOrEmpty(settings.HostName))
        {
            app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions
            {
                // This middleware is intended to be used locally for debugging. By default, HostName will
                // only have a value when running in an App Service application.
                SigningKey = ConfigurationManager.AppSettings["SigningKey"],
                ValidAudiences = new[] { ConfigurationManager.AppSettings["ValidAudience"] },
                ValidIssuers = new[] { ConfigurationManager.AppSettings["ValidIssuer"] },
                TokenHandler = config.GetAppServiceTokenHandler()
            });
        }

        config.Routes.MapHttpRoute(
              name: "DefaultApi",
              routeTemplate: "api/{controller}/{id}",
              defaults: new { id = RouteParameter.Optional }
          );
        app.UseWebApi(config);
    }

使用

设置SignalR
    public static void ConfigureSignalR(IAppBuilder app, CustomNinjectDependencyResolver resolver)
    {           
        IKernel kernel = resolver.Kernel;
        var connectionManager = resolver.Resolve<IConnectionManager>();
        var heartbeat = resolver.Resolve<ITransportHeartbeat>();
        var hubPipeline = resolver.Resolve<IHubPipeline>();

        kernel.Bind<IConnectionManager>().ToConstant(connectionManager);
        kernel.Bind<IUserIdProvider>().To<ZumoUserIdProvider>().InSingletonScope();

        var hubConfig = new HubConfiguration
        {
            Resolver = resolver,
            EnableDetailedErrors = true,
            EnableJSONP = true,
        };

        hubPipeline.AddModule(kernel.Get<LoggingHubPipelineModule>());

        app.MapSignalR(hubConfig);
    }

当我尝试转到/ api / values时,会发生这种情况

Microsoft.Azure.AppService.Authentication Verbose: 0 : Received request: GET https://kamelos-app.azurewebsites.net/api/values
Microsoft.Azure.AppService.Authentication Verbose: 0 : Found 'AppServiceAuthSession' cookie for site 'xxx.azurewebsites.net'. Length: 768.
Microsoft.Azure.AppService.Authentication Verbose: 0 : Authenticated xxx successfully using 'Session Cookie' authentication.
Exception thrown: 'System.Reflection.ReflectionTypeLoadException' in mscorlib.dll
Exception thrown: 'System.Net.WebSockets.WebSocketException' in System.Web.dll
Exception thrown: 'System.Net.WebSockets.WebSocketException' in mscorlib.dll
Exception thrown: 'System.OperationCanceledException' in mscorlib.dll
Exception thrown: 'System.OperationCanceledException' in System.Web.dll
Microsoft.Azure.AppService.Authentication Verbose: 0 : Received request: GET https://kamelos-app.azurewebsites.net/favicon.ico
Microsoft.Azure.AppService.Authentication Verbose: 0 : Exception thrown: 'System.OperationCanceledException' in mscorlib.dll
Found 'AppServiceAuthSession' cookie for site 'kamelos-app.azurewebsites.net'. Length: 768.
Exception thrown: 'System.OperationCanceledException' in mscorlib.dll
Microsoft.Azure.AppService.Authentication Verbose: 0 : Authenticated xxx successfully using 'Session Cookie' authentication.
Exception thrown: 'System.OperationCanceledException' in mscorlib.dll

尝试将SignalR降级为2.1.2无济于事。同样的问题。

更新。如果一个SignalR会话没有进行,我转到/ api / values,输出日志中有WebSocketException,但是,之后进入监控页面,那里不再是SignalR。至于监控代码:

<script type="text/javascript">
    $(function () {
        function encodeHtml(html) {
            // html still emits double quotes so we need to replace these entities to use them in attributes.
            return $("<div/>").text(html).html().replace(/\"/g, "&quot;");
        }
        var monitor = $.connection.monitor;
        $.connection.hub.logging = true;
        monitor.client.logError = function (value) {
            $('#logs').prepend('<li class="error">' + encodeHtml(value).replace('\n', '<br/>') + '</li>');
        };
        monitor.client.logWarn = function (value) {
            $('#logs').prepend('<li class="warn">' + encodeHtml(value).replace('\n', '<br/>') + '</li>');
        };
        monitor.client.logMessage = function (value) {
            $('#logs').prepend('<li class="message">' + encodeHtml(value).replace('\n', '<br/>') + '</li>');
        };
        $.connection.hub.disconnected(function () {
            setTimeout(function () {
                $.connection.hub.start();
            }, 5000);
        });
        $.connection.hub.start();
    });
</script>

但这有效,直到调用/ api / values。所以我认为这不是因为监控代码。此外,当SignalR发生故障时,整个服务器都会失败。从不同的IP地址进入也无法从SignalR获得信号。

如果监控页面没有启动,那么我会看到

Microsoft.Azure.AppService.Authentication Verbose: 0 : Received request: GET https://kamelos-app.azurewebsites.net/api/values
Microsoft.Azure.AppService.Authentication Verbose: 0 : Found 'AppServiceAuthSession' cookie for site 'xxx.azurewebsites.net'. Length: 768.
Microsoft.Azure.AppService.Authentication Verbose: 0 : Authenticated Tim Uy successfully using 'Session Cookie' authentication.
Exception thrown: 'System.Reflection.ReflectionTypeLoadException' in mscorlib.dll
'w3wp.exe' (CLR v4.0.30319: /LM/W3SVC/1848204182/ROOT-2-131345909532020945): Loaded 'D:\Windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.Data.Services.Client\v4.0_5.6.2.0__31bf3856ad364e35\Microsoft.Data.Services.Client.dll'. Cannot find or open the PDB file.
05:32:22.128 [25] DEBUG  ValuesController - requested /api/values

UPDATE2。 问题是config.DependencyResolver = resolver。当注释掉时,SignalR不会崩溃。我认为以某种方式运行apiController会导致解析器被转储。

是的,ApiController完成的那一刻,我的CustomNinjectDependencyResolver就是Disposed。为什么这样做?

1 个答案:

答案 0 :(得分:1)

事实证明违规行是

config.DependencyResolver = resolver

并且WebApi在调用ApiController后处理解析器。见Why is ASP.NET Web Api's Dependency Resolver being disposed?

  

&#34; Web API为每个请求调用一次BeginScope()方法   基础结构和Web API将在何时调用IDependencyScope.Dispose()   请求结束。&#34;