Introduction
This tip explains how to POST different kinds of data (string, XML, JSON or bytes) to a Single WCF REST Operation.
Background
When we create a WCF REST or WCF Web HTTP Service, we will expose our operations using the [OperationContract]
and with [WebGet]
or [WebInvoke]
attributes.
The service uses the WebHttpBinding
as endpoint binding. We have to configure the service to use WebHttpBehavior
as endpoint behavior which is configured with <webhttp />
. We will see these configurations also below.
The following link would be helpful for some basic understanding on Http service:
Using the Code
I am creating an empty ASP.NET application in Visual Studio 2010.
Add System.ServiceModel
and System.ServiceModel.Web
reference to the project.
Add the WCF Service to the project using the solution explorer add new item.
The above step will add a Contract with Contract implemented SVC file.
[ServiceContract]
public interface ISampleWebHttpService
{
[OperationContract]
[WebInvoke(Method="POST",
UriTemplate="DoWork",ResponseFormat=WebMessageFormat.Json)]
string DoWork(Stream stream);
}
public class SampleWebHttpService : ISampleWebHttpService
{
public string DoWork(Stream stream)
{
StreamReader reader = new StreamReader(stream);
string requestContent = reader.ReadToEnd();
requestContent = requestContent.Replace(Environment.NewLine, "")
.Replace("\\r", "")
.Replace("\\n", "")
.Replace("
", "")
.Replace("
", "")
.Replace("
", "")
.Replace("\u000a\u000d", "")
.Replace("\u000a", "")
.Replace("\u000d;", "");
return string.Format("You have posted:{0}", requestContent);
}
}
The above code shows the service contract and its implementation.
The implementation code is written to accept the any content type.
Since we are going to process the stream of data, we are going to introduce the concept of Custom ContentTypeMapper
which is used to map the request to any of the Content Types like JSON, XML or Plain Text, etc.
But in this project, even if the user provides any content type, we are going to map it to Raw. To perform this functionality, we need to create a class which implements the WebContentTypeMapper abstract
class and override the method GetMessageFormatForContentType
.
public class SampleContentTypeMapper : WebContentTypeMapper
{
public override WebContentFormat GetMessageFormatForContentType(string contentType)
{
if (string.IsNullOrWhiteSpace(contentType))
return WebContentFormat.Raw;
else
return WebContentFormat.Raw;
}
}
The above code shows the Customized Content Type Mapper.
We have created the Service Contract, Service Implementation and Custom Content Type Mapper.
We need to configure these classes and contracts to host the WCF Web Http Service.
The following code shows the configuration Service and Content Type Mapper in binding:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="WebHttpBindingSetting" maxBufferSize="2147483647"
maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
contentTypeMapper="WCFWebHttpServiceArticle.SampleContentTypeMapper,
WCFWebHttpServiceArticle, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="WCFWebHttpServiceArticle.SampleWebHttpService">
<endpoint behaviorConfiguration="WebHttpBehavior"
address="" binding="webHttpBinding"
bindingConfiguration="WebHttpBindingSetting" name="HttpEndPoint"
contract="WCFWebHttpServiceArticle.ISampleWebHttpService" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="WebHttpBehavior">
<webHttp helpEnabled="true" faultExceptionEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Run the application in debug mode and use the fiddler to compose the Request and see the Response.
Hosted Service Page
Service Help Page
Download the fiddler from this location http://www.telerik.com/download/fiddler.
Make use of the Compose tab in fiddler to compose the HTTP Post Request and enter some sample data to Post.
I am not specifying any Content Type while making HTTP Post request.
Json and Json Response
XML and XML Response
String and String Response
Points of Interest
I thought of sharing this concept, because I had a requirement like this and it might be helpful to others. Actually, I have faced many issues earlier because I was using string
as a parameter to the Operation Contract instead of a stream
, the service was throwing Bad Request Error. So I have replaced the Parameter with Stream and added the Customized ContentTypeMapper
to map the content type to Raw even if the user provides any other(JSON.XML ...).