I'm using the "HotTowel" Single Page App Template, but I'm not being able to get SignalR working. I'm getting the following error:
Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:8184/signalr/hubs
I had a kind of boilerplate using the standard MVC 4 Single Page App, with a very simple hub in place (users online counter). Everything was working fine.
After I switched to "HotTowel" it stopped working. I checked with John Papa and he gave me a suggestion to check in the Durandal side, as he mentioned he knew some fix was about to be done on some issues interfering with some routing.
main.js:
require.config({
  paths: {
    "text": "durandal/amd/text",
    "signr": "../scripts/jquery.signalR-1.0.1.min"
  }
});
define(['durandal/app', 'durandal/viewLocator', 'durandal/system', 'durandal/plugins/router', 'services/logger', "signr"],
  function (app, viewLocator, system, router, logger, sigr) {
  // Enable debug message to show in the console
  system.debug(true);
  app.start().then(function () {
    toastr.options.positionClass = 'toast-bottom-right';
    toastr.options.backgroundpositionClass = 'toast-bottom-right';
    router.handleInvalidRoute = function (route, params) {
      logger.logError('No Route Found', route, 'main', true);
    };
    // When finding a viewmodel module, replace the viewmodel string 
    // with view to find it partner view.
    router.useConvention();
    viewLocator.useConvention();
    // Adapt to touch devices
    app.adaptToDevice();
    //Show the app by setting the root view model for our application.
    app.setRoot('viewmodels/shell', 'entrance');
  });
});
Global.asax.cs:
protected void Application_Start()
{
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    // Register the default hubs route: ~/signalr/hubs
    RouteTable.Routes.MapHubs();
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}
HotTowel\index.cshtml:
<body>
  <div id="applicationHost">
    @Html.Partial("_splash")
  </div>
  @Scripts.Render("~/scripts/vendor")
    @if(HttpContext.Current.IsDebuggingEnabled) {
      <script type="text/javascript" src="~/App/durandal/amd/require.js" data-main="@Url.Content("~/App/main")"></script>
    } else {
      <!-- Remember to run the Durandal optimizer.exe to create the main-built.js  -->
      <script type="text/javascript" src="~/App/main-built.js"></script>
    }    
  <script type="text/javascript" src="~/signalr/hubs"></script>    
  @*<script src="~/App/services/hubs.js"></script>*@
</body>
(I know this probably isn't the place to put it, but I couldn't make it appear on my sources, until I've put it here) - by the way, if you can show me the correct way to do it, I'll appreciate
What else can I tell you to help me troubleshoot this? I have all references to SignalR, etc... I have a working example using another project template...
Can someone guide me ?
It should be easy enough to replicate:
I'm thinking either Durandal or Require.Js are getting in the way with this. Can someone save the day? :)
The issue is that SignalR needs its routes to be registered first. The HotTowel template attempts to 'be first' by using a PreApplicationStartMethod with WebActivator.
Couple ways to fix this.. We have WebActivator available, so you can create a new class (say SignalRConfig.cs) in App_Start like this:
[assembly: WebActivator.PreApplicationStartMethod(
typeof(SignalRConfig), "RegisterRoutes", Order = 1)]
public static class SignalRConfig
{
    public static void RegisterRoutes()
    {
        RouteTable.Routes.MapHubs();
    }
}
This will register SignalR's routes before HotTowel. Remove your call to MapHubs in global.asax as this will now be handled for you.
Alternatively, open HotTowelRouteConfig.cs and remove/comment out this attribute:
[assembly: WebActivator.PreApplicationStartMethod(
typeof(Empire.Web.App_Start.HotTowelRouteConfig), "RegisterHotTowelPreStart", Order = 2)]
Then go into global.asax and, after calling RouteTable.Routes.MapHubs(), add:
HotTowelRouteConfig.RegisterHotTowelPreStart();
After this, they should play nicely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With