diff --git a/src/RestSharp/Response/RestResponse.cs b/src/RestSharp/Response/RestResponse.cs index 859db23a7..07c24f5d3 100644 --- a/src/RestSharp/Response/RestResponse.cs +++ b/src/RestSharp/Response/RestResponse.cs @@ -34,24 +34,24 @@ public class RestResponse : RestResponse { public static RestResponse FromResponse(RestResponse response) => new() { - Content = response.Content, - RawBytes = response.RawBytes, - ContentEncoding = response.ContentEncoding, - ContentLength = response.ContentLength, - ContentType = response.ContentType, - Cookies = response.Cookies, - ErrorMessage = response.ErrorMessage, - ErrorException = response.ErrorException, - Headers = response.Headers, - ContentHeaders = response.ContentHeaders, - IsSuccessful = response.IsSuccessful, - ResponseStatus = response.ResponseStatus, - ResponseUri = response.ResponseUri, - Server = response.Server, - StatusCode = response.StatusCode, - StatusDescription = response.StatusDescription, - Request = response.Request, - RootElement = response.RootElement + Content = response.Content, + RawBytes = response.RawBytes, + ContentEncoding = response.ContentEncoding, + ContentLength = response.ContentLength, + ContentType = response.ContentType, + Cookies = response.Cookies, + ErrorMessage = response.ErrorMessage, + ErrorException = response.ErrorException, + Headers = response.Headers, + ContentHeaders = response.ContentHeaders, + IsSuccessStatusCode = response.IsSuccessStatusCode, + ResponseStatus = response.ResponseStatus, + ResponseUri = response.ResponseUri, + Server = response.Server, + StatusCode = response.StatusCode, + StatusDescription = response.StatusDescription, + Request = response.Request, + RootElement = response.RootElement }; } @@ -82,24 +82,24 @@ async Task GetDefaultResponse() { var content = bytes == null ? null : httpResponse.GetResponseString(bytes, encoding); return new RestResponse { - Content = content, - RawBytes = bytes, - ContentEncoding = httpResponse.Content.Headers.ContentEncoding, - Version = httpResponse.RequestMessage?.Version, - ContentLength = httpResponse.Content.Headers.ContentLength, - ContentType = httpResponse.Content.Headers.ContentType?.MediaType, - ResponseStatus = calculateResponseStatus(httpResponse), - ErrorException = MaybeException(), - ResponseUri = httpResponse.RequestMessage!.RequestUri, - Server = httpResponse.Headers.Server.ToString(), - StatusCode = httpResponse.StatusCode, - StatusDescription = httpResponse.ReasonPhrase, - IsSuccessful = httpResponse.IsSuccessStatusCode, - Request = request, - Headers = httpResponse.Headers.GetHeaderParameters(), - ContentHeaders = httpResponse.Content.Headers.GetHeaderParameters(), - Cookies = cookieCollection, - RootElement = request.RootElement + Content = content, + RawBytes = bytes, + ContentEncoding = httpResponse.Content.Headers.ContentEncoding, + Version = httpResponse.RequestMessage?.Version, + ContentLength = httpResponse.Content.Headers.ContentLength, + ContentType = httpResponse.Content.Headers.ContentType?.MediaType, + ResponseStatus = calculateResponseStatus(httpResponse), + ErrorException = MaybeException(), + ResponseUri = httpResponse.RequestMessage!.RequestUri, + Server = httpResponse.Headers.Server.ToString(), + StatusCode = httpResponse.StatusCode, + StatusDescription = httpResponse.ReasonPhrase, + IsSuccessStatusCode = httpResponse.IsSuccessStatusCode, + Request = request, + Headers = httpResponse.Headers.GetHeaderParameters(), + ContentHeaders = httpResponse.Content.Headers.GetHeaderParameters(), + Cookies = cookieCollection, + RootElement = request.RootElement }; Exception? MaybeException() diff --git a/src/RestSharp/Response/RestResponseBase.cs b/src/RestSharp/Response/RestResponseBase.cs index cba2eb1f8..71a415c00 100644 --- a/src/RestSharp/Response/RestResponseBase.cs +++ b/src/RestSharp/Response/RestResponseBase.cs @@ -61,9 +61,14 @@ public abstract class RestResponseBase { public HttpStatusCode StatusCode { get; set; } /// - /// Whether or not the response status code indicates success + /// Whether or not the HTTP response status code indicates success /// - public bool IsSuccessful { get; set; } + public bool IsSuccessStatusCode { get; set; } + + /// + /// Whether or not the HTTP response status code indicates success and no other error occurred (deserialization, timeout, ...) + /// + public bool IsSuccessful { get => IsSuccessStatusCode && ResponseStatus == ResponseStatus.Completed; } /// /// Description of HTTP status returned diff --git a/test/RestSharp.Tests.Integrated/StatusCodeTests.cs b/test/RestSharp.Tests.Integrated/StatusCodeTests.cs index b9d990d4e..a8f4cd8b9 100644 --- a/test/RestSharp.Tests.Integrated/StatusCodeTests.cs +++ b/test/RestSharp.Tests.Integrated/StatusCodeTests.cs @@ -37,6 +37,7 @@ public async Task ContentType_Additional_Information() { response.StatusCode.Should().Be(HttpStatusCode.OK); response.IsSuccessful.Should().BeTrue(); + response.IsSuccessStatusCode.Should().BeTrue(); } [Fact] @@ -88,6 +89,7 @@ public async Task Reports_1xx_Status_Code_Success_Accurately() { var response = await _client.ExecuteAsync(request); response.IsSuccessful.Should().BeFalse(); + response.IsSuccessStatusCode.Should().BeFalse(); } [Fact] @@ -96,6 +98,7 @@ public async Task Reports_2xx_Status_Code_Success_Accurately() { var response = await _client.ExecuteAsync(request); response.IsSuccessful.Should().BeTrue(); + response.IsSuccessStatusCode.Should().BeTrue(); } [Fact] @@ -104,6 +107,7 @@ public async Task Reports_3xx_Status_Code_Success_Accurately() { var response = await _client.ExecuteAsync(request); response.IsSuccessful.Should().BeFalse(); + response.IsSuccessStatusCode.Should().BeFalse(); } [Fact] @@ -112,6 +116,7 @@ public async Task Reports_4xx_Status_Code_Success_Accurately() { var response = await _client.ExecuteAsync(request); response.IsSuccessful.Should().BeFalse(); + response.IsSuccessStatusCode.Should().BeFalse(); } [Fact] @@ -120,6 +125,7 @@ public async Task Reports_5xx_Status_Code_Success_Accurately() { var response = await _client.ExecuteAsync(request); response.IsSuccessful.Should().BeFalse(); + response.IsSuccessStatusCode.Should().BeFalse(); } } diff --git a/test/RestSharp.Tests.Serializers.Json/NewtonsoftJsonTests.cs b/test/RestSharp.Tests.Serializers.Json/NewtonsoftJsonTests.cs index 11b370824..f1bb1f696 100644 --- a/test/RestSharp.Tests.Serializers.Json/NewtonsoftJsonTests.cs +++ b/test/RestSharp.Tests.Serializers.Json/NewtonsoftJsonTests.cs @@ -96,4 +96,47 @@ public async Task Use_JsonNet_For_Response() { actual.Should().BeEquivalentTo(expected); } + + [Fact] + public async Task DeserilizationFails_IsSuccessfull_Should_BeFalse() + { + using var server = HttpServerFixture.StartServer( + (_, response) => { + response.StatusCode = (int)HttpStatusCode.OK; + response.ContentType = "application/json"; + response.ContentEncoding = Encoding.UTF8; + response.OutputStream.WriteStringUtf8("invalid json"); + } + ); + + var client = new RestClient(server.Url).UseNewtonsoftJson(); + + var response = await client.ExecuteAsync(new RestRequest()); + + response.IsSuccessStatusCode.Should().BeTrue(); + response.IsSuccessful.Should().BeFalse(); + } + + [Fact] + public async Task DeserilizationSucceeds_IsSuccessfull_Should_BeTrue() { + var item = Fixture.Create(); + + using var server = HttpServerFixture.StartServer( + (_, response) => { + var serializer = new JsonNetSerializer(); + + response.StatusCode = (int)HttpStatusCode.OK; + response.ContentType = "application/json"; + response.ContentEncoding = Encoding.UTF8; + response.OutputStream.WriteStringUtf8(serializer.Serialize(item)!); + } + ); + + var client = new RestClient(server.Url).UseNewtonsoftJson(); + + var response = await client.ExecuteAsync(new RestRequest()); + + response.IsSuccessStatusCode.Should().BeTrue(); + response.IsSuccessful.Should().BeTrue(); + } } \ No newline at end of file diff --git a/test/RestSharp.Tests.Serializers.Json/SystemTextJsonTests.cs b/test/RestSharp.Tests.Serializers.Json/SystemTextJsonTests.cs index f100a1b73..09e4aa60a 100644 --- a/test/RestSharp.Tests.Serializers.Json/SystemTextJsonTests.cs +++ b/test/RestSharp.Tests.Serializers.Json/SystemTextJsonTests.cs @@ -51,4 +51,46 @@ public async Task Use_JsonNet_For_Response() { actual.Should().BeEquivalentTo(expected); } + + [Fact] + public async Task DeserilizationFails_IsSuccessfull_Should_BeFalse() { + using var server = HttpServerFixture.StartServer( + (_, response) => { + response.StatusCode = (int)HttpStatusCode.OK; + response.ContentType = "application/json"; + response.ContentEncoding = Encoding.UTF8; + response.OutputStream.WriteStringUtf8("invalid json"); + } + ); + + var client = new RestClient(server.Url).UseSystemTextJson(); + + var response = await client.ExecuteAsync(new RestRequest()); + + response.IsSuccessStatusCode.Should().BeTrue(); + response.IsSuccessful.Should().BeFalse(); + } + + [Fact] + public async Task DeserilizationSucceeds_IsSuccessfull_Should_BeTrue() { + var item = Fixture.Create(); + + using var server = HttpServerFixture.StartServer( + (_, response) => { + var serializer = new SystemTextJsonSerializer(); + + response.StatusCode = (int)HttpStatusCode.OK; + response.ContentType = "application/json"; + response.ContentEncoding = Encoding.UTF8; + response.OutputStream.WriteStringUtf8(serializer.Serialize(item)!); + } + ); + + var client = new RestClient(server.Url).UseSystemTextJson(); + + var response = await client.ExecuteAsync(new RestRequest()); + + response.IsSuccessStatusCode.Should().BeTrue(); + response.IsSuccessful.Should().BeTrue(); + } } \ No newline at end of file