Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

WCF REST - HTTP POST of Stream Data

5.00/5 (1 vote)
6 Dec 2014CPOL2 min read 32.7K   11  
This tip explains how to POST different kinds of data (string, XML, JSON or bytes) to a Single WCF REST Operation.

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.

Image 1

Image 2

Add System.ServiceModel and System.ServiceModel.Web reference to the project.

Image 3

Add the WCF Service to the project using the solution explorer add new item.

Image 4

The above step will add a Contract with Contract implemented SVC file.

Image 5

C#
[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("&#xD;&#xA;", "")
                        .Replace("&#xA;", "")
                                            .Replace("&#xD;", "")                                            
                        .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.

C#
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:

XML
<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

Image 6

Service Help Page

Image 7

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

Image 8

Image 9

XML and XML Response

Image 10

Image 11

String and String Response

Image 12

Image 13

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 ...).

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)