diff --git a/Gorse.NET.Tests/GorseTest.cs b/Gorse.NET.Tests/GorseTest.cs index 8b615cc..6d2b064 100644 --- a/Gorse.NET.Tests/GorseTest.cs +++ b/Gorse.NET.Tests/GorseTest.cs @@ -103,6 +103,13 @@ public void TestRecommend() Assert.That(items, Is.EqualTo(new string[] { "30", "20", "10" })); } + [Test] + public void TestRecommend_Returns_Null() + { + var items = client.GetRecommend("40"); + Assert.IsNull(items); + } + [Test] public async Task TestRecommendAsync() { @@ -117,6 +124,14 @@ public async Task TestRecommendAsync() Assert.That(items, Is.EqualTo(new string[] { "30", "20", "10" })); } + [Test] + public async Task TestRecommendAsync_Returns_Null() + { + + var items = await client.GetRecommendAsync("40"); + Assert.IsNull(items); + } + [Test] public void TestUserNeighbors() { diff --git a/Gorse.NET/Gorse.cs b/Gorse.NET/Gorse.cs index 308d7e9..9015a19 100644 --- a/Gorse.NET/Gorse.cs +++ b/Gorse.NET/Gorse.cs @@ -54,6 +54,12 @@ public class GorseException : Exception { public HttpStatusCode StatusCode { set; get; } public new string? Message { set; get; } + + public GorseException(string? message, HttpStatusCode statusCode) : base(message) + { + Message = message; + StatusCode = statusCode; + } } public class Gorse @@ -68,65 +74,65 @@ public Gorse(string endpoint, string apiKey) public Result InsertUser(User user) { - return Request(Method.Post, "api/user", user); + return Request(Method.Post, "api/user", user)!; } public Task InsertUserAsync(User user) { - return RequestAsync(Method.Post, "api/user", user); + return RequestAsync(Method.Post, "api/user", user)!; } public User GetUser(string userId) { - return Request(Method.Get, "api/user/" + userId, null); + return Request(Method.Get, "api/user/" + userId, null)!; } public Task GetUserAsync(string userId) { - return RequestAsync(Method.Get, "api/user/" + userId, null); + return RequestAsync(Method.Get, "api/user/" + userId, null)!; } public Result DeleteUser(string userId) { - return Request(Method.Delete, "api/user/" + userId, null); + return Request(Method.Delete, "api/user/" + userId, null)!; } public Task DeleteUserAsync(string userId) { - return RequestAsync(Method.Delete, "api/user/" + userId, null); + return RequestAsync(Method.Delete, "api/user/" + userId, null)!; } public Result InsertFeedback(Feedback[] feedbacks) { - return Request(Method.Post, "api/feedback", feedbacks); + return Request(Method.Post, "api/feedback", feedbacks)!; } public Task InsertFeedbackAsync(Feedback[] feedbacks) { - return RequestAsync(Method.Post, "api/feedback", feedbacks); + return RequestAsync(Method.Post, "api/feedback", feedbacks)!; } - public string[] GetRecommend(string userId) + public string[]? GetRecommend(string userId) { return Request(Method.Get, "api/recommend/" + userId, null); } - public Task GetRecommendAsync(string userId) + public Task GetRecommendAsync(string userId) { return RequestAsync(Method.Get, "api/recommend/" + userId, null); } public List GetUserNeighbors(string userId) { - return Request, Object>(Method.Get, @"api/user/{userId}/neighbors", null); + return Request, Object>(Method.Get, @"api/user/{userId}/neighbors", null)!; } public Task> GetUserNeighborsAsync(string userId) { - return RequestAsync, Object>(Method.Get, @"api/user/{userId}/neighbors", null); + return RequestAsync, Object>(Method.Get, @"api/user/{userId}/neighbors", null)!; } - public RetType Request(Method method, string resource, ReqType? req) where ReqType : class + public RetType? Request(Method method, string resource, ReqType? req) where ReqType : class { var request = new RestRequest(resource, method); if (req != null) @@ -134,35 +140,37 @@ public RetType Request(Method method, string resource, ReqType request.AddJsonBody(req); } var response = client.Execute(request); - if (response.StatusCode != HttpStatusCode.OK) + if (!response.IsSuccessStatusCode) { - throw new GorseException - { - StatusCode = response.StatusCode, - Message = response.Content - }; + throw new GorseException(message: response.Content, statusCode: response.StatusCode); } - else if (response.Content == null) + // Handle case where response content is null + if (response.Content == null) { - throw new GorseException - { - StatusCode = HttpStatusCode.InternalServerError, - Message = "unexcepted empty response" - }; + return default; } - RetType? ret = JsonSerializer.Deserialize(response.Content); - if (ret == null) + // Deserialize response content to the expected type + try { - throw new GorseException - { - StatusCode = HttpStatusCode.InternalServerError, - Message = "unexcepted null response" - }; + return JsonSerializer.Deserialize(response.Content); + } + catch (JsonException jsonEx) // Specific error handling for JSON deserialization + { + throw new GorseException( + message: $"Deserialization failed: {jsonEx}. \nResponse content: {response.Content}. \nStatus code: {response.StatusCode}", + statusCode: response.StatusCode + ); + } + catch (Exception ex) // General error handling for any other exceptions + { + throw new GorseException( + message: $"An error occurred while processing the response: {ex}. \nResponse content: {response.Content}. \nStatus code: {response.StatusCode}", + statusCode: response.StatusCode + ); } - return ret; } - public async Task RequestAsync(Method method, string resource, ReqType? req) where ReqType : class + public async Task RequestAsync(Method method, string resource, ReqType? req) where ReqType : class { var request = new RestRequest(resource, method); if (req != null) @@ -170,31 +178,33 @@ public async Task RequestAsync(Method method, string request.AddJsonBody(req); } var response = await client.ExecuteAsync(request); - if (response.StatusCode != HttpStatusCode.OK) + if (!response.IsSuccessStatusCode) + { + throw new GorseException(message: response.Content, statusCode: response.StatusCode); + } + // Handle case where response content is null + if (response.Content == null) + { + return default; + } + // Deserialize response content to the expected type + try { - throw new GorseException - { - StatusCode = response.StatusCode, - Message = response.Content - }; + return JsonSerializer.Deserialize(response.Content); } - else if (response.Content == null) + catch (JsonException jsonEx) // Specific error handling for JSON deserialization { - throw new GorseException - { - StatusCode = HttpStatusCode.InternalServerError, - Message = "unexcepted empty response" - }; + throw new GorseException( + message: $"Deserialization failed: {jsonEx}. \nResponse content: {response.Content}. \nStatus code: {response.StatusCode}", + statusCode: response.StatusCode + ); } - RetType? ret = JsonSerializer.Deserialize(response.Content); - if (ret == null) + catch (Exception ex) // General error handling for any other exceptions { - throw new GorseException - { - StatusCode = HttpStatusCode.InternalServerError, - Message = "unexcepted null response" - }; + throw new GorseException( + message: $"An error occurred while processing the response: {ex}. \nResponse content: {response.Content}. \nStatus code: {response.StatusCode}", + statusCode: response.StatusCode + ); } - return ret; } }