Simplest WCF REST Web Service


WCF allows to create a web site exposing WCF service and service endpoints. REST Web Service does not use SOAP, but returns data as JSON or XML instead.

WCF service is a DLL which should be hosted in a desktop application, or IIS.

This post is about how to create a very simple WCF REST Web Service hosted in IIS. Practical problems are:

  • What is the simplest Service.svc file such that the service will be hosted in IIS;
  • What is the simplest Web.Config file, given that our beloved bindings such as binding="basicHttpsBinding" and such won’t work with REST services (those are for SOAP envelopes). We need webHttpBinding instead!
  • How to manage whether the service will return JSON or XML;
  • How to map which parts of the URL map to which service method arguments.

Usual part

Usual interface and implementation could be in two files, or in one file.

File IService1.cs

using System.ServiceModel;
using System.ServiceModel.Web;

namespace SimplestWcfWebService
{
  [ServiceContract]
  public interface IService1
  {
    [OperationContract]
    [WebGet(UriTemplate = "Ping",
    ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json)]
    string Ping();

    [OperationContract]
    [WebGet(UriTemplate = "Bounce/{value}",
    ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json)]
    string Bounce(string value);
  }
}

 

File Service1.svc.cs

namespace SimplestWcfWebService
{
  public class Service1 : IService1
  {
    public string Ping()
    {
      return "Ping!";
    }
    public string Bounce(string value)
    {
      return $"You entered: {value}";
    }
  }
}

That’s basically all the code.

Set up IIS hosting

File Service1.svc

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

What is important here is the Factory attribute. Presence of this attribute will trigger, when processing the first REST request, creation of a host object living in IIS. The host will be hosting your custom DLL, which will be processing the requests.

Web.config file

Cool news is that the Web.config can be just empty: the below content is sufficient.

File Web.config

<?xml version="1.0"?>
<configuration>
</configuration>

Finishing VS project

Nothing else, actually. You need to have references in the .csproj file.

File SimplestWcfWebService.csproj

<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{5FE2D554-CC0D-4349-B112-2F4FBFE0E7EF}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SimplestWcfWebService</RootNamespace>
<AssemblyName>SimplestWcfWebService</AssemblyName>
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
<WcfConfigValidationEnabled>True</WcfConfigValidationEnabled>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<UseIISExpress>true</UseIISExpress>
<Use64BitIISExpress />
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
<UseGlobalApplicationHostFile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" />
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.EnterpriseServices" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.ServiceModel.Web" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Web.Services" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Content Include="Service1.svc" />
<Content Include="Web.config" />
</ItemGroup>
<ItemGroup>
<Compile Include="Service1.svc.cs">
<DependentUpon>Service1.svc</DependentUpon>
</Compile>
<Compile Include="IService1.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />
</ItemGroup>
<ItemGroup>
<None Include="Web.Debug.config">
<DependentUpon>Web.config</DependentUpon>
</None>
<None Include="Web.Release.config">
<DependentUpon>Web.config</DependentUpon>
</None>
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>38062</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:38062/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Setting up IIS site

If your project files are in C:\GitHub\sergeim\web\SimplestWcfWebService\SimplestWcfWebService, do, using the IIS manager:

  • Right-click on Default Web Site and “Add Application”
  • Set Alias as SimplestWcfWebService, and Physical path as C:\GitHub\sergeim\web\SimplestWcfWebService\SimplestWcfWebService
  • Click OK

Now, if you enter in Chrome browser, the URL

http://localhost/SimplestWcfWebService/Service1.svc/bounce/Hi%20there

then you will get the page

"You entered: Hi there"

And this is how Chrome renders the JSON-formatted response.

Edge behaves similarly: Now, from another machine, enter URL

http://b88h11-32/SimplestWcfWebService/Service1.svc/bounce/Hi%20there

and you get same rendering

"You entered: Hi there"

However, IE behaves a little differently.

Anyway, due to your actual web service consumer will be the code, the code will have to parse the JSON from the response. Thus we don’t care too much about variations in browser rendering.


Comments (0)

Skip to main content