Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Durandal / Require.JS - signalr/hubs reference not found

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:

  1. Just use the "HotTowel" template
  2. Add all SignalR references
  3. Test with my code

I'm thinking either Durandal or Require.Js are getting in the way with this. Can someone save the day? :)

like image 667
Tiago Reis Avatar asked Dec 26 '22 08:12

Tiago Reis


1 Answers

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.

like image 84
stirno Avatar answered Jan 15 '23 02:01

stirno