2011-08-14 71 views
6

我是wcf寧靜服務的新人。我無法找到問題所在,爲什麼我的健康服務給予'不好的請求'。我使用.NET 4.0。如何通過JSON請求從fiddler調用wcf restful服務?

我的服務是:

[OperationContract(Name="Add")] 
[WebInvoke(UriTemplate = "test/", Method = "POST", 
      ResponseFormat=WebMessageFormat.Json, 
      RequestFormat=WebMessageFormat.Json)] 
public int Add(Number n1) 
{ 
    res = Convert.ToInt32(n1.Number1) + Convert.ToInt32(n1.Number2); 
    return res; 
} 

的數據是..

[Serializable] 
    public class Number 
    { 
     public int Number1 { get; set; } 
     public int Number2 { get; set; } 
    } 

當我從小提琴手它的迴歸呼籲 'HTTP/1.1 400錯誤的請求'

我的提琴手請求標題是:

User-Agent: Fiddler 
Host: localhost:4217 
Content-Type: application/json; charset=utf-8 

而請求體是:

{"Number1":"7","Number2":"7"} 

和響應報頭是:

HTTP/1.1 400 Bad Request 
Server: ASP.NET Development Server/10.0.0.0 
Date: Sun, 14 Aug 2011 18:10:21 GMT 
X-AspNet-Version: 4.0.30319 
Content-Length: 5450 
Cache-Control: private 
Content-Type: text/html 
Connection: Close 

但是,如果我用C#的客戶端程序中調用這個服務就ok了。

我的客戶端代碼:

uri = "http://localhost:4217/Service1.svc/"; 
Number obj = new Number() { Number1 = 7, Number2 = 7 }; 
using (HttpResponseMessage response = new HttpClient().Post(uri+"test/", 
     HttpContentExtensions.CreateDataContract(obj))) 
{ 
    string res = response.Content.ReadAsString(); 
    return res.ToString(); 
} 

請幫我........

感謝。

回答

8

你會發現你的代碼問題的方法是enable tracing在服務器上,它會解釋問題的例外。我寫了一個簡單的測試與你的代碼,它有一個類似的錯誤(400),和痕跡有以下錯誤:

The data contract type 'WcfForums.StackOverflow_7058942+Number' cannot be 
deserialized because the required data members '<Number1>k__BackingField, 
<Number2>k__BackingField' were not found. 

數據類型標有[Serializable]序列的所有領域的對象,而不是屬性。註釋掉該屬性,該代碼實際工作了罰款(當時的類型屬於「POCO」(普通老式CLR對象)規則,序列化的所有公共字段和屬性。

public class StackOverflow_7058942 
{ 
    //[Serializable] 
    public class Number 
    { 
     public int Number1 { get; set; } 
     public int Number2 { get; set; } 
    } 
    [ServiceContract] 
    public class Service 
    { 
     [OperationContract(Name = "Add")] 
     [WebInvoke(UriTemplate = "test/", Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)] 
     public int Add(Number n1) 
     { 
      int res = Convert.ToInt32(n1.Number1) + Convert.ToInt32(n1.Number2); 
      return res; 
     } 
    } 
    public static void Test() 
    { 
     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 WebHttpBehavior()); 
     host.Open(); 
     Console.WriteLine("Host opened"); 

     WebClient c = new WebClient(); 
     c.Headers[HttpRequestHeader.ContentType] = "application/json; charset=utf-8"; 
     c.Encoding = Encoding.UTF8; 
     Console.WriteLine(c.UploadString(baseAddress + "/test/", "{\"Number1\":\"7\",\"Number2\":\"7\"}")); 

     Console.Write("Press ENTER to close the host"); 
     Console.ReadLine(); 
     host.Close(); 
    } 
} 
2

你做錯了的一件事是請求對象的格式。 Chang將其設置爲:

{ n1: { "Number1":"7","Number2":"7"} } 

參數名稱是傳遞給wcf json端點的json對象的根屬性名稱。

我在git上有一個sample wcf service。除其他外,它有一個json端點,並在Default.asmx我使用jquery來打電話給它。我建議你構建一個類似的網頁(將其託管在與WCF服務相同的網站上),通過jquery調用您的json服務,並在fiddler運行時測試該服務以獲取示例請求。這比自己構造請求更容易,也更少出錯,因爲jquery會處理標題中的大量細節。

調用我的echo服務的示例jQuery的AJAX代碼,您可以爲您服務適應如下:

$("#btnEchoString").click(function() { 
     var request = $("#request"); 
     var response = $("#response"); 
     $.ajax({ 
      url: 'EchoService.svc/JSON/Echo', 
      type: "POST", 
      contentType: "application/json; charset=utf-8", 
      data: JSON.stringify({ request: request.val() }), 
      dataType: "json", 
      success: function (data) { 
       response.val(data.d); 
      }, 
      error: function (request, status, error) { 
       //TODO: do something here 
      } 
     }); 
    }); 
+1

的「正常」使用WCF REST是使用''行爲(或者'WebHttpBehavior',如果通過代碼的話),而不是你在示例中使用的''對於,默認的BodyStyle是'Bare',這意味着你不需要用帶參數名稱的JSON對象包裝對象(默認的是'WrappedRequest')。 – carlosfigueira

+0

Carlos,感謝您的澄清! –