11

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: "
Grogh
  • 349
  • 1
  • 2
  • 10
  • Forgot to mention, solution uses IIS 7 for web server and not the apnet debugging server. – Grogh Mar 21 '11 at 22:05

5 Answers5

20

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.

Community
  • 1
  • 1
Grogh
  • 349
  • 1
  • 2
  • 10
3

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

Lei Shi
  • 101
  • 4
3

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.

Christian
  • 51
  • 3
0

I think there may be an issue in BodyStyle = WebMessageBodyStyle.WrappedRequest, which will - I think, though the documentation is wholly unclear - expect the element to be wrapped with the method name.

Set that unwrapped, and set the request body to '{"Name":"Frank"}' (notice the single quotes around it. What you are actually posting a string containing JSON. I have no idea why you would want this. It reminds me off http://thedailywtf.com/Articles/XMLd-XML.aspx where they are putting xml in their xml. You are putting JSON in your JSON.

Martijn
  • 11,964
  • 12
  • 50
  • 96
-1

Have you tried the [WebGet(UriTemplate = .. ] attribute instead of the post to see if that would work? Here is an example - http://blogs.msdn.com/b/kaevans/archive/2007/09/04/creating-a-json-service-with-webget-and-wcf-3-5.aspx

sep15ms
  • 879
  • 1
  • 8
  • 6
  • I did have a webget method defined which returned as expected, commented out currently to clean up code to focus on the post. I had that in place with a webinvoke method, and found a post on stackoverflow (can't find it back now) that said to not include that. Prior to removing I wasn't getting through at all, was recieving a 404, after removing I now get 200 responses, but no data. Didn't seem to matter if I left it as the root ("") or put an endpoint in – Grogh Mar 22 '11 at 02:44
  • What OS and version of IIS, or IIS Express or web dev server, are you using? What framework is the app pool set to? The 404 error may have been because of an issue related here http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/2ec269e3-c1ff-4d9b-9ff3-d530f1599047 – sep15ms Mar 22 '11 at 02:52
  • 2008 r2 sp1 IIS 7 with .Net 4 registered with aspnet_regiis.exe. Any pointers on where to go in IIS 7 to add the referenced dll? Also trying on win 7 sp1 with IIS installed, but I think that's IIS 7.5... still no juice though. – Grogh Mar 22 '11 at 03:21
  • Update: enabled tracing and appear to be getting an exception during deserialization... "An unrecognized element wsa encountered in the XML during deserialization which was ignored." My understanding is with the new routing in wcf 4 I shouldn't have to worry about defining endpoints. Anyone know if that's true? – Grogh Mar 22 '11 at 16:26
  • 1
    Had to vote down on this one as the OA is specifically asking about posting. The web is full of examples of GET which works easily but I came to this question looking for an answer on what needs to change for doing a POST and this answer says to use GET. – Joseph White Mar 12 '15 at 19:09