Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF REST Service JSON Post data

Tags:

json

rest

c#

post

wcf

Looking for some guidance on a wcf 4 rest service which is based on the WCF REST Template 40(CS) extension in VS2010. I've spent the last couple of days trying to get this bugger to work, reviewing other posts, and while I've gotten close, I can't seem to cross the finish line. After much frustration, it is finally hitting the service and posting (using fiddler request builder) but the method parameter is coming across as null, but it's being set properly in the request builder. I'm guessing that it may be a config issue at this point, but as the deadline looms, I'm running out of time for more research. FWIW, in debugging, the jsonstring variable is null. Self admittedly kind of a noob question as this is the first time through REST for me, any help would be much appreciated!

Thanks in advance.

web.config

<system.web>
  '<compilation debug="true" targetFramework="4.0" />
</system.web>

<system.webServer>
 <modules runAllManagedModulesForAllRequests="true">
   <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
 </modules>
</system.webServer>

<system.serviceModel>
 <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
 <standardEndpoints>
   <webHttpEndpoint>
     <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
   </webHttpEndpoint>
 </standardEndpoints>
</system.serviceModel>

global.asax.cs

   public class Global : HttpApplication
  {
      void Application_Start(object sender, EventArgs e)
      {
         RegisterRoutes();
      }

      private void RegisterRoutes()
      {
         RouteTable.Routes.Add(new ServiceRoute("Scoring", new WebServiceHostFactory(), typeof(ScoringSvc)));
      }
   }

Service code

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class ScoringSvc 
{
   [OperationContract]
   [WebInvoke
      (Method = "POST",
      BodyStyle = WebMessageBodyStyle.WrappedRequest,
      RequestFormat=WebMessageFormat.Json,
      ResponseFormat=WebMessageFormat.Json)]
   public string BOB(string jsonstring)
   {
      return "Received: " + jsonstring;
   }
}

Fiddler request header

Host: localhost
Content-Length: 20
Content-Type: application/json; charset=UTF-8

request body

{"Name":"Frank"}

Raw response from fiddler

HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 12
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 21 Mar 2011 21:31:14 GMT

"Received: "
like image 564
Grogh Avatar asked Mar 21 '11 22:03

Grogh


3 Answers

I use this one and works:

[WebInvoke(ResponseFormat = WebMessageFormat.Json, 
           RequestFormat = WebMessageFormat.Json,
           BodyStyle = WebMessageBodyStyle.WrappedRequest,
           Method = "POST",
           UriTemplate = "setExpositions?shelfId={shelfId}")]
[OperationContract]
public bool SetExpositions(int shelfId, List<WcfExposition> expositions)
{
}

where shelfId is passed in GET, and expositions are passed in the message body as JSON data.

like image 83
Christian Avatar answered Oct 19 '22 21:10

Christian


Have you tried entering {"jsonstring":"Frank"} in the request body(inside fiddler's Request Builder)?

like image 39
Lei Shi Avatar answered Oct 19 '22 23:10

Lei Shi


Stumbled across this link WCF + REST: Where is the request data? and seen Glenn's response to pass a stream to the method and then rip that apart with a streamreader into a string to get the form post data.

Modified the prototype service code as follows

[OperationContract]
[WebInvoke
   (UriTemplate="/BOB",
    Method = "POST",
    BodyStyle = WebMessageBodyStyle.WrappedRequest)]
public string BOB (Stream streamdata)
{
    StreamReader reader = new StreamReader(streamdata);
    string res = reader.ReadToEnd();
    reader.Close();
    reader.Dispose();
    return "Received: " + res;
}

And that seems to do the trick, the full json array is passed in the stream, read into the local string, and I can then attack it using json.net to serialize into / from a dictionary to pass to the business logic. Not really pretty, but functional.

like image 21
Grogh Avatar answered Oct 19 '22 21:10

Grogh