Search code examples
url-rewritingsharepoint-2007signalr

SignalR in SharePoint


My project has a need for realtime user interaction and I think SignalR will solve my need. I'm technically on a SharePoint 2007 project, although I'm exclusively in application pages and thus barely use SharePoint at all. Regardless, I'm stuck in a 2.0 framework app pool in IIS.

My first approach was to try to create a 4.0 application as a sub-site. Unfortunately, that failed miserably. That approach works in a non-SharePoint world, but it appears that SharePoint has hijacked too much of the request pipeline for this approach to work for me.

So now I'm going down the path of creating a separate IIS Site that's 4.0 and using IIS rewrite rules to fake my app into thinking a particular subdirectory (/realtime/) is local and not a separate site so that I don't have to deal with cross domain request issues. The problem is I can't get IIS rewrite rules to rewrite to another http host (e.g. http://www.mySharepoint.com/_layouts/MySite/realtime/Hello.aspx to http://realtime.mySharePoint.com/Hello.aspx).

Any help with approach #1 or approach #2 or any alternative ideas would be greatly appreciated.


Solution

  • Here is what I did... Web App with signalR .net4.0, then your SharePoint Web App .net 2.

    1. Add this to the global.asax in your Signalr project

      RouteTable.Routes.MapHttpHandlerRoute("spproxy","spproxy/{*operation}", new SharePointRProxyHandler());
      
    2. If you want to raise an event from SharePoint you can do a http POST to this new route URL for example

       http://localhost:38262/spproxy
      

      It will pass any posted data onto the httphandler below, that will then broadcast it to your clients.

    Here is the code for MapHttpHandlerRoute

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace System.Web.Routing
    {
    public class HttpHandlerRoute : IRouteHandler
    {
        private String _virtualPath = null;
        private IHttpHandler _handler = null;
    
        public HttpHandlerRoute(String virtualPath)
        {
            _virtualPath = virtualPath;
        }
    
        public HttpHandlerRoute(IHttpHandler handler)
        {
            _handler = handler;
        }
    
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            IHttpHandler result;
            if (_handler == null)
            {
                result = (IHttpHandler)System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(_virtualPath, typeof(IHttpHandler));
            }
            else
            {
                result = _handler;
            }
            return result;
        }
    }
    
    public static class RoutingExtensions
    {
        public static void MapHttpHandlerRoute(this RouteCollection routes, string routeName, string routeUrl, string physicalFile, RouteValueDictionary defaults = null, RouteValueDictionary constraints = null)
        {
            var route = new Route(routeUrl, defaults, constraints, new HttpHandlerRoute(physicalFile));
            RouteTable.Routes.Add(routeName, route);
        }
    
        public static void MapHttpHandlerRoute(this RouteCollection routes, string routeName, string routeUrl, IHttpHandler handler, RouteValueDictionary defaults = null, RouteValueDictionary constraints = null)
        {
            var route = new Route(routeUrl, defaults, constraints, new HttpHandlerRoute(handler));
            RouteTable.Routes.Add(routeName, route);
        }
    }
    }
    

    Or you could just post directly to a httphandler and get the handler to do a connection.Broadcast

    namespace SharePointRProxy
    {
     /// <summary>
     /// Summary description for SharePointRProxyHandler
     /// </summary>
     public class SharePointRProxyHandler : IHttpHandler
     {
    
         public void ProcessRequest(HttpContext context)
         {
             context.Response.ContentType = "text/plain";
             IConnectionManager connectonManager = AspNetHost.DependencyResolver.Resolve<IConnectionManager>();
             IConnection connection = connectonManager.GetConnection<MyConnection>();
    
             object payload = null; //Add payload here 'context.Request.Params["data"] ?'
    
             JavaScriptSerializer jss = new JavaScriptSerializer();
             var payloadJSON = jss.Serialize(payload);
    
             connection.Broadcast(payloadJSON);
         }
    
         public bool IsReusable
         {
             get
             {
                 return false;
             }
         }
     }
    }