2014-12-29 117 views
6

我正在製作一個應用程序,客戶端請求服務器。服務器使用flurl.Http編寫在node.js和.NET客戶端中。Flurl.Http自定義錯誤

當服務器上的請求失敗時,創建自定義錯誤消息總是有用的。事情是這樣的:

request.respond(500, { message: "targetid is mandatory" }); 

然而,這調用在客戶端和在響應中的JSON信息的FlurlHttpException丟失。

從服務器收到非成功響應代碼時,如何接收此JSON信息?

+0

我認爲我的[新答案](http://stackoverflow.com/a/28332184/62600)應該是你要找的。 –

回答

7

我剛剛發佈了一個更新Flurl.Http,使處理錯誤響應一大堆更輕鬆。這裏有一個例子:

try { 
    var t = await "http://api.com".GetJsonAsync<T>(); 
} 
catch (FlurlHttpException ex) { 
    var error = ex.GetResponseJson<TError>(); 
} 

有幾個變化:

ex.GetResponseString(); 
ex.GetResponseJson(); // returns a dynamic 

請注意,您不需要await錯誤響應體。由於await內部的catch塊在C#4.5中不受支持,所以我不希望它在這裏。然而,仍然沒有阻止;作爲原始呼叫的一部分,等待並捕獲錯誤響應主體。 (由於在正常情況下搶先將響應主體捕獲爲一個字符串可能會導致性能下降,所以我只會針對不成功的響應來執行此操作,將會拋出一個FlurlHttpException。將來,我可能會考慮使此行爲可配置。)

這些增強功能已添加到版本0.5.0中,並可在NuGet上獲得。

0

我通過編輯Flurl的源代碼解決了這個問題。 在文件FlurlMessageHandler.cs中,您會發現檢查是否發生錯誤的IsErrorCondition方法。每當響應沒有代碼2xx時,這被看作是一個錯誤,這部分我從代碼中刪除,現在我手動檢查響應是否有一個成功的代碼。

0

你可以儘管FlurlHttpException.Call失敗的響應,這是HttpCall一個實例,包含(除其他事項外)的原始HttpRequestMessageHttpResponseMessage診斷對象的身體。

獲取身體失去響應的需要異步調用的,可惜你不能await一個catch塊裏面,所以我建議捕捉catch塊和await之後荷蘭國際集團響應體內的呼叫失敗。事情是這樣的:

HttpCall failedCall = null; 

try { 
    await url.GetAsync(); 
} 
catch (FlurlHttpException ex) { 
    failedCall = ex.Call; 
} 

if (failedCall != null && failedCall.Response != null) { 
    var body = await failedCall.Response.Content.ReadAsStringAsync(); 
    // body now contains the full text of the failed response. 
} 

雖然Flurl擅長讓你從一個基本URL的響應POCO用盡可能少的噪音越好,當你需要對付失敗的響應主體是不可否認變得更加嘈雜。我打開了一個note-to-self,看看我能否在這裏想出一些捷徑。隨意評論你可能有的任何想法。

+0

在我的回答中,我展示瞭如何保持異步流程。 –

+0

@LayGonzález如果通過「保持異步流程」意味着在catch塊中等待,則不能在當前(支持的)語言/編譯器版本中執行該操作,但我明白[即將到來](http:// blog。 stephencleary.com/2014/06/await-in-catch-and-finally.html)。 –

0

我認爲將所有http錯誤作爲例外處理很有趣。不知道是否是最佳做法,但我試了一下。

我所做的是這樣的:

public static async Task<User> LoginWithEmail (string email, string password){ 
    try{ 
    return await "http://myapi.com/login" 
       .AppendPathSegment ("login") 
       .SetQueryParams (new {email = email, password = password}) 
       .WithHeader ("Accept", "application/json") 
       .GetJsonAsync<User>(); 
    }catch (FlurlHttpException e) { 
    return await e.Call.Response.Content.ReadAsStringAsync() 
        .ContinueWith<User> ((contentAsync) => { 
         throw new MyApiException(JsonConvert.DeserializeObject<MyApiError> (contentAsync.Result)); }); 
    } 
} 

這可以讓你處理成功和錯誤的情況是這樣的:

async void FakeLogin() 
{ 
    try{ 
     User user = await LoginWithEmail ("[email protected]", "fakePassword"); 
    } 
    catch(MyApiException e) { 
     MyApiError = e.Error; 
    } 
} 

基本上

對於FlurlHttpException情況,我爲ReadAsStringAsync做了一個延續,在那裏我聲明瞭繼續返回一個用戶,但在延續中我總是拋出異常。

此外

您可以重構異常處理越短:

catch (FlurlHttpException e) { 
    return await MyApiException.FromFlurlException<User>(e); 
} 
+0

您使用的是什麼版本的Visual Studio?這*可能*編譯在2015年預覽(沒有嘗試過),但不會在任何受支持的版本,因爲[你不能在一個catch塊內等待](http://stackoverflow.com/questions/8868123/await -in-捕獲塊)。 –

+0

我使用Xamarin的.Net PCL 78,我相信它是.net 4.5。它編譯並運行,但現在我不確定是否按預期運行(異步)。 –

+0

@ToddMenier現在我可以確認我能夠編譯它,因爲我使用的是Mono。如你所說,Visual Studios的.Net不允許在catch塊中使用await。 –