views:

74

answers:

2

I have a WCF REST 4.0 project based on the the WCF REST Service Template 40(CS). I'd like to expose simple service endpoint URLs without trailing slashes. For example:

  1. CarService.cs
  2. TruckService.cs

I look at the above URLs as resource requests (not directories), which is why I don't think trailing slashes are appropriate here.

Unfortunately, I can't seem to get the behavior I want because I am always redirected to /cars/ and /trucks/ with a trailing slash.

Here's how I've defined the "cars" route and service method - note that I have not included any slashes in any of the route or URI template definitions:

// Global.asax.cs
RouteTable.Routes.Add(new ServiceRoute("cars", new WebServiceHostFactory(), typeof(CarService)));

// CarService.cs
[WebGet(UriTemplate = "")]
public List<Car> GetCollection()
{
    return DataContext.GetAllCars();
}

Note that MVC does not work this way. With the MapRoute method I can route requests directly to http://www.domain.com/about without a redirect to /about/. How can I get the same behavior in WCF REST 4.0?

+1  A: 

You need a UriTemplate, Try something like this:

 [ServiceContract()]
 public interface ICarService
 {

     [OperationContract]
     [WebGet(UriTemplate = "/Car")]
     CarPool GetAllCars();

     [OperationContract]
     [WebGet(UriTemplate = "/Car/{carName}")]
     Car GetCar(string carName);

 }
Shiraz Bhaiji
Yes, but I want both a CarService and a TruckService, so I would have to add two routes in Global.asax.cs, right? And to differentiate between them, the URLs would be very verbose: e.g. http://www.domain.com/carservice/cars and http://www.domain.com/truckservice/trucks. I'd prefer to have multiple service classes *and* short URLs: e.g. http://www.domain.com/cars and http://www.domain.com/trucks
Will
You are correct that I can have slashless URLs if I was willing to list all my service methods in a *single* service class, however. But that could be hundreds of methods for a large API.
Will
+1  A: 

The primary issue that you're running into is that the current version of WCF REST causes a 307 redirect (to the "/") when you have an empty string for the UriTemplate in your WebGet attribute. As far as I know, there is no getting around this in the current version.

However, there are a couple of "middle ground" solution to your problem given that you want a solution that 1) allows you to differentiate services, and 2) have (relatively) short URIs.

First Solution You can put this in your global.asax file (per this example). You can do a service route for each service:

RouteTable.Routes.Add(new ServiceRoute("cars", new WebServiceHostFactory(), typeof(CarService)));
RouteTable.Routes.Add(new ServiceRoute("trucks", new WebServiceHostFactory(), typeof(TruckService)));

At this point you can populate your UriTemplate in each service:

[WebGet(UriTemplate = "all")]
CarPool GetAllCars();

[WebGet(UriTemplate = "{carName}")]
Car GetCar(string carName);

This will allow you URIs of:

www.domain.com/cars/all
www.domain.com/cars/123 or www.domain.com/cars/honda

similarly for trucks:

www.domain.com/trucks/all
www.domain.com/trucks/123 or www.domain.com/trucks/ford

Second Solution Use the service host from the REST Starter Kit (i.e., the WebServiceHost2Factory).

RouteTable.Routes.Add(new ServiceRoute("cars", new WebServiceHost2Factory(), typeof(CarService)));

This does not result in a 307 redirect when using the URIs that you're attempting to use above and thus, gives you exactly what you need. Though I realize that feels a little weird using that service host factory rather than the one that ships with WCF 4.

Steve Michelotti
Thanks for the info, Steve. I'd considered using your "all" suggestion already (it's a decent workaround), but I'm reluctant to give up on the canonical REST syntax I originally hoped for. I'm looking into the differences between the shipped WebServiceHostFactory and WebServiceHost2Factory, and what it is about the latter one that prevents the 307 redirect. If it's a minor change that I can grok, I'll go with that approach.
Will
Actually, I just tried using WebServiceHost2Factory and get the same redirect result.
Will
Oops - strike my second solution - you are correct in that the WebServiceHost2Factory results in the same behavior. (when I tested it, I did not have an empty UriTemplate). But the first solution will still work.
Steve Michelotti