¿Cómo obtener un punto final POST para trabajar en un servicio web alojado automáticamente (WebServiceHost)?

Por lo tanto, he estado jugando con los servicios web desde hace un tiempo, y sigo volviendo a algunos conceptos básicos, que nunca parece estar bien.

Pregunta 1:

Al usar un WebServiceHost en .NET / C #, puede definir un método / punto final como usar GET / POST / etc. Configurar un método GET es fácil y funciona de manera muy directa, y es fácil de entender cómo funciona. Por ejemplo:

[OperationContract] [WebInvoke(Method = "GET", UriTemplate = "/PutMessage/{jsonString}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)] string PutMessage(string jsonString); 

Si llamo a http: /// MyWebService / PutMessage / {MyJsonString} me pasan el método, y todo está bien (más o menos).

Pero entonces, ¿qué significa cuando defino esto como un POST en su lugar?

 [OperationContract] [WebInvoke(Method = "POST", UriTemplate = "/PutMessage/{jsonString}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)] string PutMessage(string jsonString); 

¿Qué hace UriTemplate aquí? Si hago una POST, espero que los datos no estén en el URI, sino en la “sección de datos” de la publicación. ¿Pero defino el nombre de la variable en la sección de datos? ¿Cómo sabe WebServiceHost / .NET que lo que está contenido en la “sección de datos” de la publicación debe colocarse en la variable jsonString? ¿Cómo publico los datos desde el lado del cliente (no C #, digamos JQuery en su lugar) para que se interprete correctamente en el lado del seridor?

(¿Y cómo funciona el WebMessageFormat cosas? He leído en todas partes sobre esto (MSDN, Stackoverflow, etc.) pero no he encontrado una respuesta clara y buena.)

Pregunta 2:

En mis bashs por comprender esto, pensé en hacer un método POST muy simple, como este:

 [OperationContract] [WebInvoke] string PutJSONRequest(string pc); 

Luego bash llamar a este método usando Fiddler, pero eso no funciona en absoluto. Acabo de recibir un error de 400, diciendo “HTTP / 1.1 400 Bad Request”. Tengo un punto de interrupción en la primera línea del código del método, y el método en sí no contiene nada:

 public string PutJSONRequest(string pc) { return null; } 

De nuevo, ¿cómo sabe .NET que lo que PUBLICÉ con Fiddler debería estar en la “PC de cadena”? ¿Cómo lo interpreta como una cadena y qué tipo de cadena (UT8, ASCII, etc.)?

Esta es la solicitud HTTP RAW, enviada desde Fiddler:

 POST http://:8093/AlfaCustomerApp/PutJSONRequest HTTP/1.1 User-Agent: Fiddler Host: :8093 Content-Length: 3 Content-type: application/x-www-form-urlencoded; charset=UTF-8 asd 

y no importa qué tipo de tipo de contenido utilizo, por lo que puedo ver.

La respuesta es una cosa estándar, que no tengo el control de mí mismo:

 HTTP/1.1 400 Bad Request Content-Length: 1165 Content-Type: text/html Server: Microsoft-HTTPAPI/2.0 Date: Mon, 15 Oct 2012 15:45:02 GMT [then HTML code] 

Cualquier ayuda sería apreciada. Gracias.

Creo que un código simple puede responder todas sus preguntas

 Task.Factory.StartNew(()=>StartServer()); Thread.Yield(); StartClient(); 

 void StartServer() { Uri uri = new Uri("http://localhost:8080/test"); WebServiceHost host = new WebServiceHost(typeof(WCFTestServer), uri); host.Open(); } void StartClient() { try { WebClient wc = new WebClient(); //GET string response1 = wc.DownloadString("http://localhost:8080/test/PutMessageGET/abcdef"); //returns: "fedcba" //POST with UriTemplate string response2 = wc.UploadString("http://localhost:8080/test/PutMessagePOSTUriTemplate/abcdef", JsonConvert.SerializeObject(new { str = "12345" })); //returns: fedcba NOT 54321 //POST with BodyStyle=WebMessageBodyStyle.WrappedRequest //Request: {"str":"12345"} wc.Headers["Content-Type"] = "application/json"; string response3 = wc.UploadString("http://localhost:8080/test/PutMessagePOSTWrappedRequest", JsonConvert.SerializeObject(new { str="12345" })); //POST with BodyStyle=WebMessageBodyStyle.Bare wc.Headers["Content-Type"] = "application/json"; string response4 = wc.UploadString("http://localhost:8080/test/PutMessagePOSTBare", "12345" ); } catch (WebException wex) { Console.WriteLine(wex.Message); } } 

 [ServiceContract] public class WCFTestServer { [OperationContract] [WebInvoke(Method = "GET", UriTemplate = "/PutMessageGET/{str}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)] public string PutMessageGET(string str) { return String.Join("", str.Reverse()); } [OperationContract] [WebInvoke(Method = "POST", UriTemplate = "/PutMessagePOSTUriTemplate/{str}", BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)] public string PutMessagePOSTUriTemplate(string str) { return String.Join("", str.Reverse()); } [OperationContract] [WebInvoke(Method = "POST", BodyStyle=WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)] public string PutMessagePOSTWrappedRequest(string str) { return String.Join("", str.Reverse()); } [OperationContract] [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)] public string PutMessagePOSTBare(string str) { return String.Join("", str.Reverse()); } } 

PD: puedes encontrar el JsonConvert aquí

Descubrí la respuesta. Así es como se define un método, que puede tomar los datos brutos enviados en un HTTP POST:

 [OperationContract] [WebInvoke(BodyStyle=WebMessageBodyStyle.Bare)] Stream PutMessage(Stream data); 

y la implementación es así:

 public Stream PutMessage(Stream data) { byte[] buffer = new byte[65535]; int bytesRead, totalBytes = 0; do { bytesRead = data.Read(buffer, 0, 65535); totalBytes += bytesRead; } while (bytesRead > 0); // Then you could interpret it as a String for example: string jsonString = Encoding.UTF8.GetString(buffer, 0, totalBytes); // yada yada }