2012-09-18 79 views
4

幾年前,我們爲移動應用程序開發了一個.NET Web服務。 iPhone/Android/Blackberry/WindowsPhone以及由第三方開發的所有原生應用正在調用此服務。我們增加了對JSON的支持,所以有些應用程序使用JSON調用訪問此服務,有些使用SOAP。未指定內容類型時,Web服務返回SOAP

只有當請求與HTTP標頭Content-type: application/json一起發送時,web服務纔會返回JSON。

我們遇到了一個Android平臺(特別是Galaxy Nexus)的問題,其中Content-Type標頭缺少GET請求。我們的第三方應用程序開發人員嘗試了許多解決方案,但無法找到強制發送Content-Type GET請求的方法。

但是,我們確實注意到Accept標頭設置正確並且已發送,但是在這些情況下,我發現無法更改Web服務以使用該標頭而不是Content-Type來返回JSON。

下面是示例請求,其中包含XML響應,而不是根據需要使用JSON。

GET /mobile/service.asmx/Logon?system=2&username='test'&password='1234' HTTP/1.1 
Accept: application/json 
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4) 
Connection: Keep-Alive 

而且摘自Web服務代碼:

[WebMethod(
     BufferResponse = false, 
     CacheDuration = 0 
     )] 
    [ScriptMethod(UseHttpGet = true,ResponseFormat = ResponseFormat.Json) ] 
    public LogonResponse Logon(int system, string username, string password) 
    { 
     return service.Logon(system, username, password); 
    } 

有沒有辦法迫使以某種方式,或檢查Accept頭這樣做JSON響應? (除了遷移到WCF?)

如果沒有,應用程序開發人員告訴我他們使用Spring框架發出HTTP請求。如果有關於如何使其在應用程序方面工作的解決方案,並強制發送GET請求的頭文件Content-Type,那麼也很感激!

謝謝!

回答

1

感謝您的答覆。

儘管設置內容類型並沒有解決問題,但它確實指向了我的正確方向。

下解決了這個問題對我來說:

[WebMethod( 
     BufferResponse = false, 
     CacheDuration = 0 
     )] 
    [ScriptMethod(UseHttpGet = true,ResponseFormat = ResponseFormat.Json) ] 
    public LogonResponse Logon(int system, string username, string password) 
    { 
     return SetOutput<LogonResponse>(service.Identify(username, password)); 
    } 

和實際的轉換:

public static T SetOutput<T>(object response) 
    { 
     var accept = HttpContext.Current.Request.Headers["Accept"]; 
     var ctype = HttpContext.Current.Request.ContentType; 

     if (string.IsNullOrEmpty(ctype) && !string.IsNullOrEmpty(accept)) 
      if (accept.ToLower().EndsWith("application/json")) 
      { 
       var serializer = new JavaScriptSerializer(); 
       var json = serializer.Serialize(response); 
       HttpContext.Current.Response.ContentType = "application/json"; 
       HttpContext.Current.Response.Write(json); 
       HttpContext.Current.Response.End(); 
      } 
     return (T)response; 
    } 

乾杯!

+0

祝賀。是的,對不起,我的意思是設置_response_,而不是要求(顯然)。很高興我能幫上忙。 – K3N

2

你可以試試這個(目前無法測試)。

public LogonResponse Logon(int system, string username, string password) 
{ 

    string accept = HttpContext.Current.Request.Headers("Accept"); 
    if (!string.IsNullOrEmpty(accept)) { 
     if (accept.ToLower.EndsWith("application/json")) { 
      HttpContext.Current.Response.ContentType = "application/json"; 
     } 
    }  
    return service.Logon(system, username, password); 
} 

編輯:更新請求響應

0

使用以下也包住整個事情與預期的「d」元素:

public static T SetOutput<T>(T response) 
    { 
     var accept = HttpContext.Current.Request.Headers["Accept"]; 
     var ctype = HttpContext.Current.Request.ContentType; 

     if (string.IsNullOrEmpty(ctype) && !string.IsNullOrEmpty(accept)) 
      if (accept.ToLower().EndsWith("application/json")) 
      { 
       var wrapper = new JSONWrapper<T> {d = response}; 
       var serializer = new JavaScriptSerializer(); 
       var json = serializer.Serialize(wrapper); 
       HttpContext.Current.Response.ContentType = "application/json"; 
       HttpContext.Current.Response.Write(json); 
       HttpContext.Current.Response.End(); 
      } 

     return response; 
    } 

    public class JSONWrapper<T> 
    { 
     public T d { set; get; } 
    }