WCF – Removing .svc from RESTful URIs

Addressability is one of the four properties of Resource-Oriented Architectures. An application is addressable if it exposes the interesting aspects of its data set through resources. And resources are exposed through their unique URIs.1 By default, the endpoints of an IIS hosted WCF service have the service file name in their URLs.2 For example,

http://www.mydomain.com/Service1.svc/resource1

While not un-RESTful, the “Service1.svc” part doesn’t add to the addressability of an ROA service. A resource URI should indicate the relationship of its resource to other resources. The example above would typically mean that resource1 is subordinate to Service1.svc, which isn’t the case. In fact, Service1.svc isn’t a resource at all and does not relate to any interesting aspect of our data.

With WCF we have the option of removing the .svc file reference from our URIs. First, use Visual Studio 2010 to create a new .Net 4(+) WCF Service Application.

Open the web.config.

The default, VS generated configuration is:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

Add the aspNetCompatibilityEnabled=”true” attribute to the serviceHostingEnvironment element on line 18:

...
      </serviceBehaviors>
    </behaviors>
 <serviceHostingEnvironment multipleSiteBindingsEnabled="true"  aspNetCompatibilityEnabled="true" />
  </system.serviceModel>
...

Now add a Global.asax file to your project.

Open the Global.asax and add the following code on line 17:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using System.Web.Routing;
using System.ServiceModel.Activation;

namespace YourNameSpaceHere
{
   public class Global : System.Web.HttpApplication
   {

      protected void Application_Start(object sender, EventArgs e)
      {
         RouteTable.Routes.Add(new ServiceRoute("", new WebServiceHostFactory(), typeof(Service1)));
      }

      protected void Session_Start(object sender, EventArgs e)
      {
          //...

Add a reference to System.ServiceModel.Activation if it is not already there:

Open the IService1.cs file and replace the auto-generated code with the following. This has nothing to do with removing the .svc file. It’s just to give you a working service. Don’t forget to use your namespace on line 9.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace YourNameSpaceHere
{
   [ServiceContract]
   public interface IService1
   {
      [OperationContract]
      [WebInvoke(Method = "GET",
          ResponseFormat = WebMessageFormat.Xml,
          UriTemplate = "artist")]
      Artist GetArtist();

   }

   [DataContract] 
   
   public class Artist
   {  [DataMember]
      public string FirstName { get; set; }
      [DataMember]
      public string LastName { get; set; }
      [DataMember]
      public string Grammys { get; set; }
      
      public Artist(string firstName, string lastName, string grammys)
      {
         this.FirstName = firstName;
         this.LastName = lastName;
         this.Grammys = grammys;
      }
   }
}

Open Service1.svc.cs and replace the code with this. Again, this is just for a working service.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace YourNameSpaceHere
{
   public class Service1 : IService1
   {
      public Artist GetArtist()
      {
         Artist player = new Artist("LastName", "FirstName", "0");
         return player;
      }

   }
}

Now modify Service1.svc.cs by adding a reference to System.ServiceModel.Activation and decorating the implementation class with the [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] attribute. This is part of removing the .svc file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.ServiceModel.Activation;

namespace YourNameSpaceHere
{
   [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
   public class Service1 : IService1
   {
      public Artist GetArtist()
      {
         Artist player = new Artist("LastName", "FirstName", "0");
         return player;
      }

   }
}

Finally, right click the Services1.svc file and View Markup:

Add the Factory=”System.ServiceModel.Activation.WebServiceHostFactory” attribute as follows:

<%@ ServiceHost Language="C#" Debug="true" 
Service="YourNameSpaceHere.Service1" CodeBehind="Service1.svc.cs" 
Factory="System.ServiceModel.Activation.WebServiceHostFactory"%>

And that’s all there is to do! Right click on the Services1.svc file and View in Browser. You’ll find the .svc file is no longer an endpoint:

Now browse to http://localhost:55685/artist to see the results:

<Artist xmlns="http://schemas.datacontract.org/2004/07/rest" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <FirstName>LastName</FirstName> 
  <Grammys>0</Grammys> 
  <LastName>FirstName</LastName> 
</Artist>

If you’ve built a WCF rest service before, you’ll also notice how we avoided all that configuration mess in the Web.config!

Many thanks to Steve Michelotti and his blog post “RESTful WCF Services with No svc file and No config”. Check out his article for more details on configuring WCF to not use the .svc file. He’ll also show you how to configure WCF to generate a help file for your services.


1. Richardson, Leonard and Ruby, Sam. RESTful Web Services. Sebastopol: O’Reilly Media, Inc., 2008. Ebook

2. WCF services hosted in IIS are represented as special content files (.svc files) inside the IIS application. It provides information used by IIS to initiate the WCF runtime and start the service. By default, the .svc file name is used as the base address for the service.

Tagged with: , ,
Posted in REST, WCF, Web Services
One comment on “WCF – Removing .svc from RESTful URIs
  1. sam says:

    This was really helpful. Thanks!

Advertisement