150 lines
5.7 KiB
C#
150 lines
5.7 KiB
C#
using System.Net;
|
|
using System.Text.Json;
|
|
|
|
namespace RobotNet10.CustomConfigurationEditor.Services.API;
|
|
|
|
/// <summary>
|
|
/// Helper class để parse error messages từ HTTP responses
|
|
/// </summary>
|
|
public static class HttpErrorHelper
|
|
{
|
|
/// <summary>
|
|
/// Extract user-friendly error message từ HttpResponseMessage
|
|
/// </summary>
|
|
public static async Task<string> GetErrorMessageAsync(HttpResponseMessage response)
|
|
{
|
|
try
|
|
{
|
|
// Try to read error message from response body
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
|
|
if (!string.IsNullOrWhiteSpace(content))
|
|
{
|
|
// Try to parse as JSON error object
|
|
try
|
|
{
|
|
using var doc = JsonDocument.Parse(content);
|
|
var root = doc.RootElement;
|
|
|
|
// Check for common error property names
|
|
if (root.TryGetProperty("error", out var errorProp))
|
|
{
|
|
var errorMsg = errorProp.GetString();
|
|
if (!string.IsNullOrWhiteSpace(errorMsg))
|
|
return errorMsg;
|
|
}
|
|
|
|
if (root.TryGetProperty("message", out var messageProp))
|
|
{
|
|
var message = messageProp.GetString();
|
|
if (!string.IsNullOrWhiteSpace(message))
|
|
return message;
|
|
}
|
|
|
|
if (root.TryGetProperty("errors", out var errorsProp) && errorsProp.ValueKind == JsonValueKind.Array)
|
|
{
|
|
var errors = errorsProp.EnumerateArray()
|
|
.Select(e => e.GetString())
|
|
.Where(s => !string.IsNullOrWhiteSpace(s))
|
|
.ToList();
|
|
|
|
if (errors.Count > 0)
|
|
return string.Join("; ", errors);
|
|
}
|
|
|
|
// If it's a simple string, return it
|
|
if (root.ValueKind == JsonValueKind.String)
|
|
{
|
|
return root.GetString() ?? GetDefaultMessage(response.StatusCode);
|
|
}
|
|
}
|
|
catch (JsonException)
|
|
{
|
|
// If JSON parsing fails, check if content is a simple error message
|
|
if (content.Length < 500) // Reasonable length for error message
|
|
{
|
|
return content;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex) when (ex is HttpRequestException or ObjectDisposedException)
|
|
{
|
|
// Fall through to default message
|
|
}
|
|
|
|
return GetDefaultMessage(response.StatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Extract user-friendly error message từ Exception
|
|
/// </summary>
|
|
public static string GetErrorMessage(Exception ex)
|
|
{
|
|
// Check for HttpRequestException
|
|
if (ex is HttpRequestException httpEx)
|
|
{
|
|
// Try to extract meaningful message
|
|
var message = httpEx.Message;
|
|
|
|
// Remove technical details
|
|
if (message.Contains("net_http_message_not_success_statuscode"))
|
|
{
|
|
return "Unable to connect to server. Please check your network connection.";
|
|
}
|
|
|
|
if (message.Contains("timeout"))
|
|
{
|
|
return "Request timeout. Please try again.";
|
|
}
|
|
|
|
if (message.Contains("connection"))
|
|
{
|
|
return "Unable to connect to server. Please check your network connection.";
|
|
}
|
|
|
|
return message;
|
|
}
|
|
|
|
// Check for TaskCanceledException (often timeout)
|
|
if (ex is TaskCanceledException)
|
|
{
|
|
return "Request timeout. Please try again.";
|
|
}
|
|
|
|
// Return original message if it's user-friendly
|
|
var exMessage = ex.Message;
|
|
if (!string.IsNullOrWhiteSpace(exMessage) &&
|
|
!exMessage.Contains("net_http") &&
|
|
!exMessage.Contains("StatusCode") &&
|
|
!exMessage.Contains("Bad Request") &&
|
|
exMessage.Length < 200)
|
|
{
|
|
return exMessage;
|
|
}
|
|
|
|
// Default fallback
|
|
return "An error occurred. Please try again or contact the administrator.";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get default error message based on HTTP status code
|
|
/// </summary>
|
|
private static string GetDefaultMessage(HttpStatusCode statusCode)
|
|
{
|
|
return statusCode switch
|
|
{
|
|
HttpStatusCode.BadRequest => "Invalid data. Please check your input.",
|
|
HttpStatusCode.Unauthorized => "You do not have permission to perform this action.",
|
|
HttpStatusCode.Forbidden => "You do not have access to this resource.",
|
|
HttpStatusCode.NotFound => "The requested data was not found.",
|
|
HttpStatusCode.Conflict => "Data already exists or conflicts with existing data.",
|
|
HttpStatusCode.InternalServerError => "Server error. Please try again later.",
|
|
HttpStatusCode.ServiceUnavailable => "Service is temporarily unavailable. Please try again later.",
|
|
HttpStatusCode.GatewayTimeout => "Request timeout. Please try again.",
|
|
_ => $"Error: {statusCode}. Please try again."
|
|
};
|
|
}
|
|
}
|
|
|