HttpClientJsonExtensions better handling for failed requests (imported from Blazor PR 1660) (#4788)

This commit is contained in:
Steve Sanderson 2018-12-14 17:06:03 +00:00 committed by GitHub
parent 93127b39e8
commit 8a9df6c873
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 163 additions and 0 deletions

View File

@ -101,6 +101,10 @@ namespace Microsoft.AspNetCore.Components
Content = new StringContent(requestJson, Encoding.UTF8, "application/json")
});
// Make sure the call was successful before we
// attempt to process the response content
response.EnsureSuccessStatusCode();
if (typeof(T) == typeof(IgnoreResponse))
{
return default;

View File

@ -0,0 +1,159 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.JSInterop;
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNetCore.Components.Test
{
public class HttpClientJsonExtensionsTest
{
const string TestUri = "http://example.com/some/uri";
[Fact]
public async Task GetJson_Success()
{
// Arrange
var httpClient = new HttpClient(new TestHttpMessageHandler(req =>
{
Assert.Equal(TestUri, req.RequestUri.AbsoluteUri);
return Task.FromResult(CreateJsonResponse(HttpStatusCode.OK, new Person
{
Name = "Abc",
Age = 123
}));
}));
// Act
var result = await httpClient.GetJsonAsync<Person>(TestUri);
// Assert
Assert.Equal("Abc", result.Name);
Assert.Equal(123, result.Age);
}
[Fact]
public async Task GetJson_Failure()
{
// Arrange
var httpClient = new HttpClient(new TestHttpMessageHandler(req =>
{
Assert.Equal(TestUri, req.RequestUri.AbsoluteUri);
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.NotFound));
}));
// Act/Assert
var ex = await Assert.ThrowsAsync<HttpRequestException>(
() => httpClient.GetJsonAsync<Person>(TestUri));
Assert.Contains("404 (Not Found)", ex.Message);
}
[Theory]
[InlineData("Put")]
[InlineData("Post")]
[InlineData("Patch")]
[InlineData("Delete")]
[InlineData("MyArtificialMethod")]
public async Task SendJson_Success(string httpMethodString)
{
var httpMethod = new HttpMethod(httpMethodString);
var requestContent = new { MyProp = true, OtherProp = "Hello" };
// Arrange
var httpClient = new HttpClient(new TestHttpMessageHandler(async req =>
{
Assert.Equal(httpMethod, req.Method);
Assert.Equal(TestUri, req.RequestUri.AbsoluteUri);
Assert.Equal(Json.Serialize(requestContent), await ((StringContent)req.Content).ReadAsStringAsync());
return CreateJsonResponse(HttpStatusCode.OK, new Person
{
Name = "Abc",
Age = 123
});
}));
// Act
var result = await Send(httpClient, httpMethodString, requestContent);
// Assert
Assert.Equal("Abc", result.Name);
Assert.Equal(123, result.Age);
}
[Theory]
[InlineData("Put")]
[InlineData("Post")]
[InlineData("Patch")]
[InlineData("Delete")]
[InlineData("MyArtificialMethod")]
public async Task SendJson_Failure(string httpMethodString)
{
var httpMethod = new HttpMethod(httpMethodString);
var requestContent = new { MyProp = true, OtherProp = "Hello" };
// Arrange
var httpClient = new HttpClient(new TestHttpMessageHandler(async req =>
{
Assert.Equal(httpMethod, req.Method);
Assert.Equal(TestUri, req.RequestUri.AbsoluteUri);
Assert.Equal(Json.Serialize(requestContent), await ((StringContent)req.Content).ReadAsStringAsync());
return new HttpResponseMessage(HttpStatusCode.BadGateway);
}));
// Act/Assert
var ex = await Assert.ThrowsAsync<HttpRequestException>(
() => Send(httpClient, httpMethodString, requestContent));
Assert.Contains("502 (Bad Gateway)", ex.Message);
}
HttpResponseMessage CreateJsonResponse(HttpStatusCode statusCode, object content)
{
return new HttpResponseMessage(statusCode)
{
Content = new StringContent(Json.Serialize(content))
};
}
Task<Person> Send(HttpClient httpClient, string httpMethodString, object requestContent)
{
// For methods with convenience overloads, show those overloads work
switch (httpMethodString)
{
case "post":
return httpClient.PostJsonAsync<Person>(TestUri, requestContent);
case "put":
return httpClient.PutJsonAsync<Person>(TestUri, requestContent);
default:
return httpClient.SendJsonAsync<Person>(new HttpMethod(httpMethodString), TestUri, requestContent);
}
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class TestHttpMessageHandler : HttpMessageHandler
{
private readonly Func<HttpRequestMessage, Task<HttpResponseMessage>> _sendDelegate;
public TestHttpMessageHandler(Func<HttpRequestMessage, Task<HttpResponseMessage>> sendDelegate)
{
_sendDelegate = sendDelegate;
}
protected override void Dispose(bool disposing)
=> base.Dispose(disposing);
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
=> _sendDelegate(request);
}
}
}