views:

194

answers:

1

Hi all,

Let's say that I have specified the following WCF REST Service at the address "http://localhost/MyRESTService/MyRESTService.svc"

[ServiceContract]
public interface IMyRESTService
{
[OperationContract]
[WebInvoke(
  Method = "POST",
  UriTemplate = "/receive")]
string Receive(string text);

Now I can call my REST service in Fiddler using the address "http://localhost/MyRESTService/MyRESTService.svc/receive" and it works (I'll get a return value).

But what if I want to send parameters to my REST Service? Should I change my interface definition to look like this:

[ServiceContract]
public interface IMyRESTService
{
[OperationContract]
[WebInvoke(
  Method = "POST",
  UriTemplate = "/receive/{text}")]
string Receive(string text);

Now if I'll call the REST Service in Fiddler using the address "http://localhost/MyRESTService/MyRESTService.svc/receive/mytext" it works (it sends the parameter "mytext" and I'll get a return value). So is this the correct URI for sending parameters via POST?

What confuses me is that I don't know how to use this URI exactly in code at the same time when I'm sending parameters. I have this following code which is almost complete for sending POST data to a WCF REST Service but I'm in stuck with how to take parameters into account with URI.

Dictionary<string, string> postDataDictionary = new Dictionary<string, string>();
      postDataDictionary.Add("text", "mytext");

      string postData = "";
      foreach (KeyValuePair<string, string> kvp in postDataDictionary)
      {
        postData += string.Format("{0}={1}&", HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value));
      }
      postData = postData.Remove(postData.Length - 1); 

      Uri uri = new Uri("http://localhost/MyRESTService/MyRESTService.svc/receive");
      HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
      req.Method = "POST";
      byte[] postArray = Encoding.UTF8.GetBytes(postData);
      req.ContentType = "application/x-www-form-urlencoded";
      req.ContentLength = postArray.Length;

      Stream dataStream = req.GetRequestStream();
      dataStream.Write(postArray, 0, postArray.Length);
      dataStream.Close();

      HttpWebResponse response = (HttpWebResponse)req.GetResponse();
      Stream responseStream = response.GetResponseStream();
      StreamReader reader = new StreamReader(responseStream);

      string responseString = reader.ReadToEnd();

      reader.Close();
      responseStream.Close();
      response.Close();

If I'll want to send parameters (e.g. "mytext") in code via POST should the URI code be either

this

Uri uri = new Uri("http://localhost/MyRESTService/MyRESTService.svc/receive");

or this (this works but it doesn't make any sense since parameters should be added other way and not directly to the URI address)

Uri uri = new Uri("http://localhost/MyRESTService/MyRESTService.svc/receive/mytext");

I'm glad if you can help me, it can't be so difficult with WCF REST Services.

A: 

So if you want to send raw data such as XML to your WCF REST Service (and also return), here is how to do it. But I have to say that before I found this solution I spend a lot of time googling frustrated as all examples were just talking about sending parameters in the URI (come on, the common scenario is to send XML and you can't do that properly in the URI). And when finally I found the right code examples it came up that it wasn't enough in WCF as I got the error "400 Bad Request". This error was caused by the fact that WCF can't use my raw XML if I don't force it by overriding it with some custom code (come on, what were you thinking Microsoft?, fix this in the next version of .NET Framework). So I'm not satisfied at all if doing such a basic thing can be so hard and time consuming).

** IMyRESTService.cs (server-side code) **

[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare)]
Stream Receive(Stream text);

** client-side code **

XmlDocument MyXmlDocument = new XmlDocument();
MyXmlDocument.Load(FilePath);
byte[] RequestBytes = Encoding.GetEncoding("iso-8859-1").GetBytes(MyXmlDocument.OuterXml);

Uri uri = new Uri("http://localhost/MyRESTService/MyRESTService.svc/Receive");

Request.ContentLength = RequestBytes.Length;

Request.Method = "POST";

Request.ContentType = "text/xml";

Stream RequestStream = Request.GetRequestStream();
RequestStream.Write(RequestBytes, 0, RequestBytes.Length);
RequestStream.Close();

HttpWebResponse response = (HttpWebResponse)Request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string ResponseMessage = reader.ReadToEnd();
response.Close();

** XmlContentTypeMapper.cs (server-side custom code which forces WCF to accept raw XML) **

public class XmlContentTypeMapper : WebContentTypeMapper
{
public override WebContentFormat GetMessageFormatForContentType(string contentType)
{
return WebContentFormat.Raw;
}
}

** Web.config (server-side configuration settings for utilizing the custom code)

<endpoint binding="customBinding" bindingConfiguration="XmlMapper" contract="MyRESTService.IMyRESTService"
           behaviorConfiguration="webHttp"    />

<bindings>
  <customBinding>
    <binding name="XmlMapper">
      <webMessageEncoding webContentTypeMapperType="MyRESTService.XmlContentTypeMapper, MyRESTService"/>
      <httpTransport manualAddressing="true"/>
    </binding>
  </customBinding>
</bindings>

Invoke a WCF Web Service with an HTTP POST http://social.msdn.microsoft.com/forums/en-us/wcf/thread/4074F4C5-16CC-470C-9546-A6FB79C998FC