Flurl.Http自定义错误

9

我在开发一个应用程序,客户端向服务器发送请求。服务器使用node.js编写,客户端使用flurl.Http编写的.NET。

当服务器上的请求失败时,创建自定义错误消息总是很有用的。例如:

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

然而,这会在客户端触发一个FlurlHttpException,并且响应中的JSON信息会丢失。

当从服务器接收到非成功响应代码时,我该如何接收此JSON信息呢?


我认为我的 新答案 应该是你在寻找的东西。 - Todd Menier
回答[已更新] - 获取错误响应的方法现在是异步的。 - Todd Menier
3个回答

14

由于Flurl专注于以尽可能少的按键次数从URL到反序列化响应体,因此经常会被问及如何处理错误响应,其中响应体几乎总是与成功响应不同。这就是为什么Flurl默认在非2XX响应上抛出异常,以便您可以像这样处理错误响应:(参见链接)

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

有几种变化:

ex.GetResponseStringAsync();
ex.GetResponseJsonAsync(); // returns a dynamic

有一个设置项 OnError,我能否使用它来包装 FlurlHttpException 为另一种类型并重新抛出它?顺便说一下,感谢您提供的这个很棒的框架。 - user1679671
是的,这实际上是OnError的一个相当常见的用例。https://flurl.io/docs/configuration/#event-handlers - Todd Menier
有人知道这个例子中的<TError>类型是从哪里来的吗?似乎没有参考资料。 - jaygeek

1
我认为将所有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 ("fakeEmail@me.com", "fakePassword");
  }
  catch(MyApiException e) {
       MyApiError = e.Error;
  }
}

基本上

对于FlurlHttpException情况,我会在ReadAsStringAsync中进行延续,其中我声明延续返回一个User,但在延续内部,我总是抛出异常。

此外

您可以重构异常处理为以下简短形式:

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

你使用的是哪个版本的Visual Studio?这可能会在2015预览版中编译(我没有尝试过),但在任何支持的版本中都不会,因为你不能在catch块中使用await - Todd Menier
我正在使用Xamarin的.Net PCL 78,我相信它是.net 4.5。它可以编译和运行,但现在我不确定它是否按预期运行(异步)。 - Lay González
1
@ToddMenier 现在我可以确认我能够编译它是因为我使用了Mono。正如你所说,Visual Studios的.Net不允许在catch块中使用await。 - Lay González

0
我通过编辑Flurl的源代码解决了这个问题。 在文件FlurlMessageHandler.cs中,您会找到方法IsErrorCondition,该方法检查是否发生了错误。每当响应没有2xx代码时,都会被视为错误,我从代码中删除了这部分内容,现在我手动检查响应是否具有成功代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接