Flurl.Http自定义错误

我正在做一个客户端请求到服务器的应用程序。 服务器使用flurl.Http编写在node.js和.NET客户端。

当服务器上的请求失败时,创build自定义错误消息始终是有用的。 像这样的东西:

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

但是,这会在客户端调用FlurlHttpException,并且响应中的JSON信息会丢失。

如果从服务器收到非成功的响应代码,我怎样才能收到这个JSON信息?

我刚刚发布了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错误响应正文。 由于在C#4.5中不支持在catch块内部进行await ,所以我不想在这里。 但是,仍然没有阻止; 作为原始呼叫的一部分,等待并捕获错误响应主体。 (由于在正常情况下抢占响应主体作为string在正常情况下可能是一个性能问题,所以我只做非FlurlHttpExceptionexception响应,将来我会考虑使这个行为是可configuration的。

这些增强function已在0.5.0版本中添加,并可在NuGet上使用 。

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

通过FlurlHttpException.Call一个实例), HttpCall失败响应的主体,该FlurlHttpException.Call是一个包含(除其他之外)原始HttpRequestMessageHttpResponseMessage的诊断对象。

从响应中获取主体需要一个asynchronous调用,不幸的是你不能await一个catch块,所以我build议捕获该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尽可能less的噪音,但无可否认,当你需要处理一个失败的响应正文时会变得更加嘈杂。 我已经打开了一个自己的笔记 ,看看我能不能在这里find一些捷径。 随意评论您可能有的任何想法。

我认为把所有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做了一个延续,在那里我声明了inheritance来返回一个User,但是在继续的时候我总是抛出一个exception。

另外

您可以将exception处理重构为:

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