diff --git a/CryptoExchange.Net/BaseClient.cs b/CryptoExchange.Net/BaseClient.cs
index 6fa01d9..d2c03f2 100644
--- a/CryptoExchange.Net/BaseClient.cs
+++ b/CryptoExchange.Net/BaseClient.cs
@@ -69,6 +69,13 @@ namespace CryptoExchange.Net
///
protected CallResult ValidateJson(string data)
{
+ if (string.IsNullOrEmpty(data))
+ {
+ var info = "Empty data object received";
+ log.Write(LogVerbosity.Error, info);
+ return new CallResult(null, new DeserializeError(info));
+ }
+
try
{
return new CallResult(JToken.Parse(data), null);
diff --git a/CryptoExchange.Net/Interfaces/IResponse.cs b/CryptoExchange.Net/Interfaces/IResponse.cs
index 816d920..1b5d9f1 100644
--- a/CryptoExchange.Net/Interfaces/IResponse.cs
+++ b/CryptoExchange.Net/Interfaces/IResponse.cs
@@ -1,9 +1,11 @@
using System.IO;
+using System.Net;
namespace CryptoExchange.Net.Interfaces
{
public interface IResponse
{
+ HttpStatusCode StatusCode { get; }
Stream GetResponseStream();
void Close();
}
diff --git a/CryptoExchange.Net/Objects/CallResult.cs b/CryptoExchange.Net/Objects/CallResult.cs
index af1d214..78eee85 100644
--- a/CryptoExchange.Net/Objects/CallResult.cs
+++ b/CryptoExchange.Net/Objects/CallResult.cs
@@ -1,4 +1,6 @@
-namespace CryptoExchange.Net.Objects
+using System.Net;
+
+namespace CryptoExchange.Net.Objects
{
public class CallResult
{
@@ -21,4 +23,17 @@
Error = error;
}
}
+
+ public class WebCallResult: CallResult
+ {
+ ///
+ /// The status code of the response. Note that a OK status does not always indicate success, check the Success parameter for this.
+ ///
+ public HttpStatusCode? ResponseStatusCode { get; set; }
+
+ public WebCallResult(HttpStatusCode? code, T data, Error error): base(data, error)
+ {
+ ResponseStatusCode = code;
+ }
+ }
}
diff --git a/CryptoExchange.Net/Requests/Request.cs b/CryptoExchange.Net/Requests/Request.cs
index 721959b..8b64c4f 100644
--- a/CryptoExchange.Net/Requests/Request.cs
+++ b/CryptoExchange.Net/Requests/Request.cs
@@ -67,7 +67,7 @@ namespace CryptoExchange.Net.Requests
public async Task GetResponse()
{
- return new Response(await request.GetResponseAsync().ConfigureAwait(false));
+ return new Response((HttpWebResponse)await request.GetResponseAsync().ConfigureAwait(false));
}
}
}
diff --git a/CryptoExchange.Net/Requests/Response.cs b/CryptoExchange.Net/Requests/Response.cs
index a467f47..f8bc037 100644
--- a/CryptoExchange.Net/Requests/Response.cs
+++ b/CryptoExchange.Net/Requests/Response.cs
@@ -6,9 +6,11 @@ namespace CryptoExchange.Net.Requests
{
public class Response : IResponse
{
- private readonly WebResponse response;
+ private readonly HttpWebResponse response;
- public Response(WebResponse response)
+ public HttpStatusCode StatusCode => response.StatusCode;
+
+ public Response(HttpWebResponse response)
{
this.response = response;
}
diff --git a/CryptoExchange.Net/RestClient.cs b/CryptoExchange.Net/RestClient.cs
index 13c79f4..8400b2f 100644
--- a/CryptoExchange.Net/RestClient.cs
+++ b/CryptoExchange.Net/RestClient.cs
@@ -115,13 +115,13 @@ namespace CryptoExchange.Net
/// Whether or not the request should be authenticated
/// Whether or not the resulting object should be checked for missing properties in the mapping (only outputs if log verbosity is Debug)
///
- protected virtual async Task> ExecuteRequest(Uri uri, string method = Constants.GetMethod, Dictionary parameters = null, bool signed = false, bool checkResult = true) where T : class
+ protected virtual async Task> ExecuteRequest(Uri uri, string method = Constants.GetMethod, Dictionary parameters = null, bool signed = false, bool checkResult = true) where T : class
{
log.Write(LogVerbosity.Debug, "Creating request for " + uri);
if (signed && authProvider == null)
{
log.Write(LogVerbosity.Warning, $"Request {uri.AbsolutePath} failed because no ApiCredentials were provided");
- return new CallResult(null, new NoApiCredentialsError());
+ return new WebCallResult(null, null, new NoApiCredentialsError());
}
var request = ConstructRequest(uri, method, parameters, signed);
@@ -138,7 +138,7 @@ namespace CryptoExchange.Net
if (!limitResult.Success)
{
log.Write(LogVerbosity.Debug, $"Request {uri.AbsolutePath} failed because of rate limit");
- return new CallResult(null, limitResult.Error);
+ return new WebCallResult(null, null, limitResult.Error);
}
if (limitResult.Data > 0)
@@ -152,16 +152,20 @@ namespace CryptoExchange.Net
log.Write(LogVerbosity.Debug, $"Sending {method}{(signed ? " signed" : "")} request to {request.Uri} {paramString ?? ""}");
var result = await ExecuteRequest(request).ConfigureAwait(false);
if(!result.Success)
- return new CallResult(null, result.Error);
+ return new WebCallResult(result.ResponseStatusCode, null, result.Error);
var jsonResult = ValidateJson(result.Data);
if(!jsonResult.Success)
- return new CallResult(null, jsonResult.Error);
+ return new WebCallResult(result.ResponseStatusCode, null, jsonResult.Error);
if (IsErrorResponse(jsonResult.Data))
- return new CallResult(null, ParseErrorResponse(jsonResult.Data));
-
- return Deserialize(jsonResult.Data, checkResult);
+ return new WebCallResult(result.ResponseStatusCode, null, ParseErrorResponse(jsonResult.Data));
+
+ var desResult = Deserialize(jsonResult.Data, checkResult);
+ if (!desResult.Success)
+ return new WebCallResult(result.ResponseStatusCode, null, desResult.Error);
+
+ return new WebCallResult(result.ResponseStatusCode, desResult.Data, null);
}
///
@@ -258,7 +262,7 @@ namespace CryptoExchange.Net
///
/// The request object to execute
///
- private async Task> ExecuteRequest(IRequest request)
+ private async Task> ExecuteRequest(IRequest request)
{
var returnedData = "";
try
@@ -272,12 +276,15 @@ namespace CryptoExchange.Net
log.Write(LogVerbosity.Debug, "Data returned: " + returnedData);
}
+ var statusCode = response.StatusCode;
response.Close();
- return new CallResult(returnedData, null);
+ return new WebCallResult(statusCode, returnedData, null);
}
catch (WebException we)
{
var response = (HttpWebResponse)we.Response;
+ var statusCode = response?.StatusCode;
+
try
{
using (var reader = new StreamReader(response.GetResponseStream()))
@@ -289,7 +296,7 @@ namespace CryptoExchange.Net
response.Close();
var jsonResult = ValidateJson(returnedData);
- return !jsonResult.Success ? new CallResult(null, jsonResult.Error) : new CallResult(null, ParseErrorResponse(jsonResult.Data));
+ return !jsonResult.Success ? new WebCallResult(statusCode, null, jsonResult.Error) : new WebCallResult(statusCode, null, ParseErrorResponse(jsonResult.Data));
}
catch (Exception)
{
@@ -300,18 +307,18 @@ namespace CryptoExchange.Net
{
infoMessage += $" | {we.Status} - {we.Message}";
log.Write(LogVerbosity.Warning, infoMessage);
- return new CallResult(null, new WebError(infoMessage));
+ return new WebCallResult(0, null, new WebError(infoMessage));
}
infoMessage = $"Status: {response.StatusCode}-{response.StatusDescription}, Message: {we.Message}";
log.Write(LogVerbosity.Warning, infoMessage);
response.Close();
- return new CallResult(null, new ServerError(infoMessage));
+ return new WebCallResult(statusCode, null, new ServerError(infoMessage));
}
catch (Exception e)
{
log.Write(LogVerbosity.Error, $"Unknown error occured: {e.GetType()}, {e.Message}, {e.StackTrace}");
- return new CallResult(null, new UnknownError(e.Message + ", data: " + returnedData));
+ return new WebCallResult(null, null, new UnknownError(e.Message + ", data: " + returnedData));
}
}