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:
- CarService.cs
- http://www.domain.com/cars - GET returns a list of all cars
- http://www.domain.com/cars/123 - GET returns a single car with ID 123
- TruckService.cs
- http://www.domain.com/trucks - GET returns a list of all trucks
- http://www.domain.com/trucks/456 - GET returns a single truck with ID 456
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?
Try changing your code in the Global.asax from...
Routes.Add(new ServiceRoute("cars", new WebServiceHostFactory(), typeof(CarService)));
RouteTable.Routes.Add(new ServiceRoute("trucks", new WebServiceHostFactory(), typeof(TruckService)));
...to...
WebServiceHostFactory factory = new WebServiceHostFactory();
Routes.Add(new ServiceRoute("cars", factory, typeof(CarService)));
RouteTable.Routes.Add(new ServiceRoute("trucks", factory, typeof(TruckService)));
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:
At this point you can populate your UriTemplate in each service:
This will allow you URIs of:
similarly for trucks:
Second Solution Use the service host from the REST Starter Kit (i.e., the WebServiceHost2Factory).
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.
A bit more reusable:
I was dealing with this exact problem and ran across this snippet in the MS online docs:
I realized that my route pattern matched the directory my service was hosted in. It appears that a directory is treated the same as a physical file, and route patterns that match a directory are ignored as well. So following the documentation, I set the RouteExistingFiles property to "true" on the RouteCollection. My service now seems to be routing the requests correctly and I've been able to keep the REST syntax that I love so very very much.
Older question but here's how I solved the problem with a WCF4 REST service (using the RouteTable in Global.asax to add ServiceRoutes). IIS7 is configured so that by the time the service is invoked I have an empty relative path so the handling method's UriTemplate is empty like Will's Car example. I used a rewrite rule in the service's web.config file to add a "/" if needed. It always matches the path then checks the original URI ({REQUEST_URI}) to see if it contains a path without a trailing "/".
Try putting this in the Global.asax.cs