PortableRest
PortableRest copied to clipboard
NullReferenceException if returned Content is null and success status code
Using the latest 3.0.1 version of Portable Rest.
When I call SendAsync() that does a PUT request, I get back a 400 Bad Request by the Portable Rest library. However, I had Fiddler running and I can see that the request actually succeeded (200) and there was no content returned.
Digging in to the source , it seems to me that the exception occurs in this method when it does a response.Content.ReadAsStringAsync() if Content is null -
In RestClient.cs -
private static async Task
just was writing a unit test where the mocked HttpMessageHandler I had set the response code to success (200) but not setting the content, and I was getting this error as well. I finally tracked down the method causing the issue and came to write up the issue, but found it's already here. So just adding on this would be nice to be fixed.
Defensive checks should be around it, in case some service returns back a good code but not a NoContent code and no content.
Thanks for pointing this out, and sorry I missed it. I will see about getting a fix out today, and adding some unit tests.
@Mikescott8, can you please post the unit test you used to recreate this scenario?
Thanks!
Below are two tests, the differences are in the Asserts and ONE LINE in the Arrange. The one line missing is the setting the Content in the HttpResponseMessage.
Hope these are enough to help you build tests that you need/want.
[TestMethod]
public void PortableRestClient_SendsBackBadRequest_When200CodeIsSetButNoContent()
{
var sut = new PortableRest.RestClient
{
BaseUrl = "http://test.com/"
};
var handler = new Mock<HttpMessageHandler>();
handler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>())
.Returns(() => Task.FromResult(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK
}));
sut.HttpHandler = handler.Object;
// act
var restRequest = new RestRequest
{
Resource = "/",
Method = HttpMethod.Get,
};
var response =
sut.SendAsync<string>(restRequest)
.Result;
// assert
response.Exception.Should().NotBeNull();
response.HttpResponseMessage.StatusCode.Should().Be(HttpStatusCode.BadRequest);
}
[TestMethod]
public void PortableRestClient_SendsContent_When200CodeIsSetAndContent()
{
var sut = new PortableRest.RestClient
{
BaseUrl = "http://test.com/"
};
var handler = new Mock<HttpMessageHandler>();
handler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>())
.Returns(() => Task.FromResult(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("Good response.")
}));
sut.HttpHandler = handler.Object;
// act
var restRequest = new RestRequest
{
Resource = "/",
Method = HttpMethod.Get,
};
var response =
sut.SendAsync<string>(restRequest)
.Result;
// assert
response.Exception.Should().BeNull();
response.HttpResponseMessage.StatusCode.Should().Be(HttpStatusCode.OK);
response.HttpResponseMessage.Content.As<StringContent>().ReadAsStringAsync().Result.Should().Be("Good response.");
}