views:

85

answers:

1

I have a WCF service that lives side-by-side with an MVC2 web site. I'd like for my URL for the service to look like this:

http://localhost/projdir/Service

The MVC site is in its infancy so it still has all its boilerplate controllers etc.

The following code works at first glance in global.asax:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.Add(new ServiceRoute("Service", new ServiceHostFactory(), 
               typeof(MyService)));

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", 
              id = UrlParameter.Optional } // Parameter defaults
    );
}

The service appears just where I described and works as advertised. Great.

However, I just noticed that ordering my code this way changes all of my ActionLink's. For example, the "About" tab on the MVC site now appears like this:

http://localhost/projdir/Service?action=About&controller=Home

This is obviously incorrect (it should be http://localhost/projdir/Home/About/ ).

If I move the ServiceRoute addition below the default MapRoute() call, then I get a missing controller error. (Actually I get a "StructureMapControllerFactory did not return an instance of a controller" error, because I'm wired up with StructureMap, duh, it's not a controller to begin with.)

Interestingly, it only seems to be affecting the output of Html.ActionLink(). I can manually type in http://localhost/projdir/Home/About/ and get to the correct page.

What horribly obvious newbie mistake am I making?

+2  A: 

Try moving the Service route after the MVC route. But to avoid the "missing controller" error that you got before, add the MVC route with a Route Constraint. These route constraints can be Regex - basically you'd want your route constraint to be any controller that is not "Service". When a request for "Service" is requested, it will make it fall through and his the WCF Service Route.

Steve Michelotti
Thanks! I used `new { controller = "^{?!Service}"}` as the constraint and it worked like a charm. Do you understand why the service route cannot be before the MVC route though?
roufamatic
The {controller} and {action} tokens are special tokens that are implicit in MVC always (you can define your own tokens too but these are *always* there). When you put the service route first, it can't find those tokens anywhere in the pattern you've defined for your route, so it's just appending them as query strings. So it's getting quite confused when the service route is first. Typically you want to order your routes so the most "specific" routes are defined first. Glad to hear it's working for you now.
Steve Michelotti
Thanks, that's helpful. Correction for future googlers: the pattern I used was actually `^(?!Service).*`
roufamatic