0

我创建了一个运行良好的 MVC (4) Web API。它有一个简单的登录方法,当找不到用户时会抛出异常。

除了 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 时,将返回一个名为 User 的对象......就像一个魅力。当我使用错误的用户名和/或密码调用此方法时,API 会引发异常(未找到用户),但 ExecutePost 方法也会引发异常,并且网页会显示一个漂亮的、黄色的、红色的字母页面普通用户无法理解的错误。原因很简单:API 传回的数据与对象 User 中可以放入的数据不一样。

所以,我想做的是从 API 反序列化异常,在一个名为 Error 的对象中,并将其返回给 MVC 网站的控制器,这样我就可以将错误“找不到用户”放在正确的页面上网站的设计。

做这个的最好方式是什么?尝试捕捉所有动作?我觉得不对...所以建议非常受欢迎。

我发现的大多数东西都是 API 端的东西,但我想在站点端获取和处理异常。

提前致谢

4

1 回答 1

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在尝试将响应反序列化为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进行反序列化操作,以便您可以优雅地处理返回数据的任何问题,如果由于某种原因无法将数据转换为User对象。

于 2013-10-07T10:27:29.983 回答