RESTful WCF web service POST task

I cannot pass parameters to the wcf web service. My web method:

[OperationContract] [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "playersJson2")] List<Person> GetPlayers(string name1, string name2); 

When I make an HTTP request, I got a 200 OK response with the correct json form, but the web service does not seem to be able to get the parameters (name1, name2). Wireshark shows the following:
enter image description here

Do you see something wrong?

Update. Not sure if that matters, but my service uses "webHttpBinding" and the mail request is from Android.

+4
source share
4 answers

WCF does not support forms / encoded data out of the box. Other answers mentioned some alternatives (get input as a stream, change the request to JSON). Another alternative that does not force you to modify the request or operation is to use custom formatting that understands the requests programmed in form. The code below shows the one that does this.

 public class MyWebHttpBehavior : WebHttpBehavior { protected override IDispatchMessageFormatter GetRequestDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint) { bool isRequestWrapped = this.IsRequestWrapped(operationDescription.Behaviors.Find<WebInvokeAttribute>()); IDispatchMessageFormatter originalFormatter = base.GetRequestDispatchFormatter(operationDescription, endpoint); if (isRequestWrapped) { return new MyFormUrlEncodedAwareFormatter( operationDescription, originalFormatter, this.GetQueryStringConverter(operationDescription)); } else { return originalFormatter; } } private bool IsRequestWrapped(WebInvokeAttribute wia) { WebMessageBodyStyle bodyStyle; if (wia.IsBodyStyleSetExplicitly) { bodyStyle = wia.BodyStyle; } else { bodyStyle = this.DefaultBodyStyle; } return bodyStyle == WebMessageBodyStyle.Wrapped || bodyStyle == WebMessageBodyStyle.WrappedRequest; } class MyFormUrlEncodedAwareFormatter : IDispatchMessageFormatter { const string FormUrlEncodedContentType = "application/x-www-form-urlencoded"; OperationDescription operation; IDispatchMessageFormatter originalFormatter; QueryStringConverter queryStringConverter; public MyFormUrlEncodedAwareFormatter(OperationDescription operation, IDispatchMessageFormatter originalFormatter, QueryStringConverter queryStringConverter) { this.operation = operation; this.originalFormatter = originalFormatter; this.queryStringConverter = queryStringConverter; } public void DeserializeRequest(Message message, object[] parameters) { if (IsFormUrlEncodedMessage(message)) { XmlDictionaryReader bodyReader = message.GetReaderAtBodyContents(); bodyReader.ReadStartElement("Binary"); byte[] bodyBytes = bodyReader.ReadContentAsBase64(); string body = Encoding.UTF8.GetString(bodyBytes); NameValueCollection pairs = HttpUtility.ParseQueryString(body); Dictionary<string, string> values = new Dictionary<string, string>(); foreach (var key in pairs.AllKeys) { values.Add(key, pairs[key]); } foreach (var part in this.operation.Messages[0].Body.Parts) { if (values.ContainsKey(part.Name)) { string value = values[part.Name]; parameters[part.Index] = this.queryStringConverter.ConvertStringToValue(value, part.Type); } else { parameters[part.Index] = GetDefaultValue(part.Type); } } } else { this.originalFormatter.DeserializeRequest(message, parameters); } } public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result) { throw new NotSupportedException("This is a request-only formatter"); } private static bool IsFormUrlEncodedMessage(Message message) { object prop; if (message.Properties.TryGetValue(WebBodyFormatMessageProperty.Name, out prop)) { if (((WebBodyFormatMessageProperty)prop).Format == WebContentFormat.Raw) { if (message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out prop)) { if (((HttpRequestMessageProperty)prop).Headers[HttpRequestHeader.ContentType].StartsWith(FormUrlEncodedContentType)) { return true; } } } } return false; } private static object GetDefaultValue(Type type) { if (type.IsValueType) { return Activator.CreateInstance(type); } else { return null; } } } } [ServiceContract] public class Service { [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)] public string Concat(string text1, string text2) { return text1 + text2; } [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)] public int Add(int x, int y) { return x + y; } } class Program { public static void SendRequest(string uri, string method, string contentType, string body) { HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri); req.Method = method; if (!String.IsNullOrEmpty(contentType)) { req.ContentType = contentType; } if (body != null) { byte[] bodyBytes = Encoding.UTF8.GetBytes(body); req.GetRequestStream().Write(bodyBytes, 0, bodyBytes.Length); req.GetRequestStream().Close(); } HttpWebResponse resp; try { resp = (HttpWebResponse)req.GetResponse(); } catch (WebException e) { resp = (HttpWebResponse)e.Response; } Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription); foreach (string headerName in resp.Headers.AllKeys) { Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]); } Console.WriteLine(); Console.WriteLine(new StreamReader(resp.GetResponseStream()).ReadToEnd()); Console.WriteLine(); Console.WriteLine(" *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* "); Console.WriteLine(); } static void Main(string[] args) { string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); host.AddServiceEndpoint(typeof(Service), new WebHttpBinding(), "").Behaviors.Add(new MyWebHttpBehavior()); host.Open(); Console.WriteLine("Host opened"); SendRequest(baseAddress + "/Add", "POST", "application/json", "{\"x\":22,\"y\":33}"); SendRequest(baseAddress + "/Add", "POST", "application/x-www-form-urlencoded", "x=22&y=33"); SendRequest(baseAddress + "/Add", "POST", "application/json", "{\"x\":22,\"z\":33}"); SendRequest(baseAddress + "/Add", "POST", "application/x-www-form-urlencoded", "x=22&z=33"); SendRequest(baseAddress + "/Concat", "POST", "application/json", "{\"text1\":\"hello\",\"text2\":\" world\"}"); SendRequest(baseAddress + "/Concat", "POST", "application/x-www-form-urlencoded", "text1=hello&text2=%20world"); SendRequest(baseAddress + "/Concat", "POST", "application/json", "{\"text1\":\"hello\",\"text9\":\" world\"}"); SendRequest(baseAddress + "/Concat", "POST", "application/x-www-form-urlencoded", "text1=hello&text9=%20world"); } } 
+4
source

It looks like you need to parse your message guide ...

You can look here , for example

0
source

The only thing that looks out of place is playerJson2 , but that is only because I have never used UriTemplate before. Can you make it work without a UriTemplate and just send a message to /WcfService1/Service1.svc/GetPlayers ? Are there any other WCF services that you work in the project?

-1
source

In this case, you need to set the correct Content-Type , which is application/json .

Sorry for misunderstanding your question. Update the UriTemplate as follows:

 [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "playersJson2?name1={name1}&name2={name2}")] 
-1
source

All Articles