让POST端点在自托管(WebServiceHost)C#webservice中工作?

所以,我一直在搞乱webservices一段时间,我不断回到一些基础知识,我似乎永远不会对。

问题1:

在.NET / C#中使用WebServiceHost时,可以使用GET / POST / etc定义方法/端点。 设置GET方法很简单,它可以直接工作,并且很容易理解它是如何工作的。 例如:

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

如果我调用http:/// MyWebService / PutMessage / {MyJsonString},我会传递该方法,并且一切都很好(或多或少)。

但是,当我将其定义为POST时,这意味着什么呢?

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

UriTemplate在这做什么? 如果我进行POST,我希望数据不包含在URI中,而是包含在post的“数据部分”中。 但是我在数据部分中定义变量名称吗? WebServiceHost / .NET如何知道post的“数据部分”中包含的内容将被放入变量jsonString中? 我如何从客户端发布数据(不是C#,而是让JQuery代替),以便在serer端正确解释?

(以及WebMessageFormat如何处理事情?我已经阅读了所有关于此的内容(MSDN,Stackoverflow等),但没有找到明确而好的答案。)

问题2:

在我试图理解这一点时,我想我会做一个非常简单的POST方法,如下所示:

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

然后我尝试使用Fiddler调用此方法,但这根本不起作用。 我刚收到400错误,说“HTTP / 1.1 400 Bad Request”。 我在方法代码的第一行有一个断点,该方法本身不包含任何内容:

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

再一次,.NET如何知道我使用Fiddler发布的内容应该包含在“string pc”中? 它如何将其解释为字符串,以及什么类型的字符串(UT8,ASCII等)?

这是从Fiddler发送的RAW HTTP请求:

 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 

而且就我所知,我使用的内容类型无关紧要。

回应是标准的事情,我无法控制自己:

 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] 

任何帮助,将不胜感激。 谢谢。

我认为一个简单的代码可以回答你的所有问题

 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()); } } 

PS:你可以在这里找到JsonConvert

我找到了答案。 这是如何定义一个方法,可以获取HTTP POST中发送的原始数据:

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

并且实现是这样的:

 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 }