/// <summary>
        /// Method mostly copied from Microsoft.AspNet.SignalR OwinExtensions class, but without external dependency on Katana.
        /// </summary>
        /// <param name="configuration">The <see cref="HubConfiguration"/> to use.</param>
        /// <param name="startupEnv">Startup parameters.</param>
        /// <param name="next">Next <see cref="AppFunc"/> in pipeline.</param>
        /// <returns><see cref="AppFunc"/> ready for use.</returns>
        public static Func <IDictionary <string, object>, Task> BuildHubFunc(HubConfiguration configuration, IDictionary <string, object> startupEnv, AppFunc next)
        {
            if (configuration == null)
            {
                throw new ArgumentException("No configuration provided");
            }

            var resolver = configuration.Resolver;

            if (resolver == null)
            {
                throw new ArgumentException("No dependency resolver provider");
            }

            var token = startupEnv.GetValueOrDefault("owin.CallCancelled", CancellationToken.None);

            string instanceName = startupEnv.GetValueOrDefault("host.AppName", Guid.NewGuid().ToString());

            var protectedData = new DefaultProtectedData();

            resolver.Register(typeof(IProtectedData), () => protectedData);

            // If the host provides trace output then add a default trace listener
            var traceOutput = startupEnv.GetValueOrDefault("host.TraceOutput", (TextWriter)null);

            if (traceOutput != null)
            {
                var hostTraceListener = new TextWriterTraceListener(traceOutput);
                var traceManager      = new TraceManager(hostTraceListener);
                resolver.Register(typeof(ITraceManager), () => traceManager);
            }

            // Try to get the list of reference assemblies from the host
            IEnumerable <Assembly> referenceAssemblies = startupEnv.GetValueOrDefault("host.ReferencedAssemblies",
                                                                                      (IEnumerable <Assembly>)null);

            if (referenceAssemblies != null)
            {
                // Use this list as the assembly locator
                var assemblyLocator = new EnumerableOfAssemblyLocator(referenceAssemblies);
                resolver.Register(typeof(IAssemblyLocator), () => assemblyLocator);
            }

            resolver.InitializeHost(instanceName, token);

            var hub = new HubDispatcherMiddleware(new KatanaShim(next), configuration);

            return(async env =>
            {
                await hub.Invoke(new OwinContext(env));

                if (!env.ContainsKey("owin.ResponseStatusCode"))
                {
                    env["owin.ResponseStatusCode"] = 200;
                }
            });
        }
Example #2
0
        private static IAppBuilder UseSignalRMiddleware <T>(this IAppBuilder builder, params object[] args)
        {
            ConnectionConfiguration configuration = null;

            // Ensure we have the conversions for MS.Owin so that
            // the app builder respects the OwinMiddleware base class
            SignatureConversions.AddConversions(builder);

            if (args.Length > 0)
            {
                configuration = args[args.Length - 1] as ConnectionConfiguration;

                if (configuration == null)
                {
                    throw new ArgumentException(Resources.Error_NoConfiguration);
                }

                var resolver = configuration.Resolver;

                if (resolver == null)
                {
                    throw new ArgumentException(Resources.Error_NoDependencyResolver);
                }

                var env = builder.Properties;
                CancellationToken token = env.GetShutdownToken();

                // If we don't get a valid instance name then generate a random one
                string instanceName = env.GetAppInstanceName() ?? Guid.NewGuid().ToString();

                // Use the data protection provider from app builder and fallback to the
                // Dpapi provider
                IDataProtectionProvider provider = builder.GetDataProtectionProvider();
                IProtectedData          protectedData;

                // If we're using DPAPI then fallback to the default protected data if running
                // on mono since it doesn't support any of this
                if (provider == null && MonoUtility.IsRunningMono)
                {
                    protectedData = new DefaultProtectedData();
                }
                else
                {
                    if (provider == null)
                    {
                        provider = new DpapiDataProtectionProvider(instanceName);
                    }

                    protectedData = new DataProtectionProviderProtectedData(provider);
                }

                resolver.Register(typeof(IProtectedData), () => protectedData);

                // If the host provides trace output then add a default trace listener
                TextWriter traceOutput = env.GetTraceOutput();
                if (traceOutput != null)
                {
                    var hostTraceListener = new TextWriterTraceListener(traceOutput);
                    var traceManager      = new TraceManager(hostTraceListener);
                    resolver.Register(typeof(ITraceManager), () => traceManager);
                }

                // Try to get the list of reference assemblies from the host
                IEnumerable <Assembly> referenceAssemblies = env.GetReferenceAssemblies();
                if (referenceAssemblies != null)
                {
                    // Use this list as the assembly locator
                    var assemblyLocator = new EnumerableOfAssemblyLocator(referenceAssemblies);
                    resolver.Register(typeof(IAssemblyLocator), () => assemblyLocator);
                }

                resolver.InitializeHost(instanceName, token);
            }

            builder.Use(typeof(T), args);

            // BUG 2306: We need to make that SignalR runs before any handlers are
            // mapped in the IIS pipeline so that we avoid side effects like
            // session being enabled. The session behavior can be
            // manually overridden if user calls SetSessionStateBehavior but that shouldn't
            // be a problem most of the time.
            builder.UseStageMarker(PipelineStage.PostAuthorize);

            return(builder);
        }