2013-10-07 49 views
0

我創建了一個可以正常工作的MVC(4)Web API。它有一個簡單的登錄方法,當用戶找不到時拋出異常。從MVC API到MVC站點的異常給出了錯誤

除了API我創建了一個簡單的網站,通過HttpClient的調用API:

public T ExecutePost<T>(string apiUrl, IEnumerable<KeyValuePair<string, string>> postData) { 
    HttpContent content = null; 

    if (postData != null) 
     content = new FormUrlEncodedContent(postData); 

    var a = _client.PostAsync(apiUrl, content).ContinueWith(httpResponseMessage => 
     JsonConvert.DeserializeObject<T>(httpResponseMessage.Result.Content.ReadAsStringAsync().Result) 
    ); 

    return a.Result; 
} 

您可以調用該方法,

ExecutePost<User>("url_to_controller_action_api", list_with_keys_and_values_to_post) 

當這個方法調用與POSTDATA-fiels的API用戶名和密碼(兩者都是正確的並且由系統知道),稱爲用戶的對象將被返回...像魅力一樣工作。 當我用錯誤的用戶名和/或密碼調用這個方法時,API會拋出一個異常(用戶找不到),但ExecutePost方法也會拋出一個異常,並且網頁顯示一個很好的,黃色的,紅色的字母頁面有一些普通用戶不理解的錯誤。原因很簡單:從API返回的數據與可放入對象User中的數據不同。

所以,我想要做的是從API中反序列化一個名爲Error的對象,並將其返回給MVC網站的控制器,這樣我就可以將錯誤「User not found」放在網頁的正確設計。

這樣做的最好方法是什麼?嘗試在所有行動中抓住?對我來說感覺不舒服......所以建議比歡迎。

我發現的大部分東西都是API端的東西,但我想在網站端獲取並處理異常。

在此先感謝

+0

我不是沿着邊界拋出異常,而是遵循寧靜的方法,讓web-api返回一個符合你的異常要求的狀態碼。所以對於沒有找到的用戶來說,404有你的httpclient讀取狀態碼,然後做出相應的反應,或者對json進行反序列化或者顯示錯誤。 – Slicksim

回答

1

在您的Web API,當你發現一個無效的登錄,確保了HttpResponseException獲取與401(HttpStatusCode.Unauthorized)狀態代碼拋出。

//login failed: 
var resp = new HttpResponseMessage(HttpStatusCode.Unauthorized) 
       { 
        Content = new StringContent("Invalid Username or password") 
       }; 
      throw new HttpResponseException(resp); 

在調用代碼,然後你可以首先,如果httpResponseMessage.StatusCode==HttpStatusCode.OK嘗試deserialise響應爲User前檢查。

var a = _client.PostAsync(apiUrl, content).ContinueWith(httpResponseMessage => { 
if (httpResponseMessage.Status!=HttpStatus.OK) 
{ 
    string ErrorMessage = httpResponseMessage.Result.Content.ReadAsStringAsync(); 
    //and whatever you want to do with that error message here 
} 
else 
{ 
try 
    { 
     var user = JsonConvert.DeserializeObject<T>(httpResponseMessage.Result.Content.ReadAsStringAsync().Result); 
    } 
    catch(Exception ex) 
    { 
     //honest to goodness unrecoverable failure on the webapi. 
     //all you can do here is fail gracefully to the caller. 
    } 
}//endif (Status OK) 
}//end anonymous function 
); 

如果不是200,那麼你可以執行第二次檢查,看它是否是一個401(並有無效的登錄一些具體的處理)或更一般的500(一些在服務器上出了錯)等,並獲得異常(「無效的用戶名或密碼」)的實際的錯誤信息發送回客戶端:

var errorMessage = httpResponseMessage.Content.ReadAsStringAsync().Result;

最後,哪怕是200,那麼你應該仍然try...catch的deserialisation操作,如果出於任何原因數據無法處理,您可以優雅地處理返回數據的任何問題變成User對象。

+0

聽起來像一個很好的計劃。但是...在控制器中,我執行:var user = GetUserFromAPI(username,password)。方法GetUserFromAPI調用代碼,如我的第一篇文章中所示,它期望一個對象用戶返回。當httpResponseMessage.StatusCode!= HttpStatusCode.OK時,如何在控制器中使用它?像ModelState一樣。AddModelError(string.Empty,「用戶名/密碼不正確」);其他錯誤可能是:用戶被阻止,等待激活 –

+0

請參閱我上面編輯的答案;要麼使用該模式,要麼修改webapi,以便在未找到用戶時不會引發異常,而是返回具有某種可檢測「不良」狀態的User對象。但是,您仍然需要嘗試/趕上反序列化,以防萬一......我沒有看到任何其他方式來做到這一點? –