WCF REST Service JSON Post data

2020-02-08 09:07发布

问题:

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: "

回答1:

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.



回答2:

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.



回答3:

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



回答4:

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.



回答5:

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



标签: c# wcf json rest post