.NET MAUI中如何处理API返回的ProblemDetails响应
解决RequestProvider.PutAsync方法的错误返回问题
背景
我基于微软的.NET MAUI参考应用开发项目,其中的RequestProvider服务提供了与API交互的PutAsync方法,但该方法仅能返回泛型TResult类型。当API返回验证或其他错误时,会返回ProblemDetails格式的响应,我已经定义了ProblemDetailsWithErrors类来接收这类错误信息,现在需要修改PutAsync方法,使其能在出错时返回错误信息,成功时返回目标对象。
现有PutAsync方法代码
public async Task<TResult> PutAsync<TResult>(string uri, TResult data, string token = "", string header = "") { HttpClient httpClient = GetOrCreateHttpClient(token); if (!string.IsNullOrEmpty(header)) { RequestProvider.AddHeaderParameter(httpClient, header); } var content = new StringContent(JsonSerializer.Serialize(data)); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); HttpResponseMessage response = await httpClient.PutAsync(uri, content).ConfigureAwait(false); await RequestProvider.HandleResponse(response).ConfigureAwait(false); TResult result = await response.Content.ReadFromJsonAsync<TResult>(); return result; }
修改方案一:返回包含结果和错误的包装类
1. 定义通用响应包装类
创建泛型类同时承载成功结果与错误信息:
public class ApiResponse<TResult> { public TResult SuccessResult { get; set; } public ProblemDetailsWithErrors ErrorResult { get; set; } public bool IsSuccess => ErrorResult == null; }
2. 修改PutAsync方法
调整返回类型为ApiResponse<TResult>,根据响应结果序列化对应对象:
public async Task<ApiResponse<TResult>> PutAsync<TResult>(string uri, TResult data, string token = "", string header = "") { HttpClient httpClient = GetOrCreateHttpClient(token); if (!string.IsNullOrEmpty(header)) { RequestProvider.AddHeaderParameter(httpClient, header); } var content = new StringContent(JsonSerializer.Serialize(data)); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); HttpResponseMessage response = await httpClient.PutAsync(uri, content).ConfigureAwait(false); try { await RequestProvider.HandleResponse(response).ConfigureAwait(false); var successResult = await response.Content.ReadFromJsonAsync<TResult>(); return new ApiResponse<TResult> { SuccessResult = successResult }; } catch (Exception) { var errorResult = await response.Content.ReadFromJsonAsync<ProblemDetailsWithErrors>(); return new ApiResponse<TResult> { ErrorResult = errorResult }; } }
3. 调用修改后的方法
通过IsSuccess区分场景,分别处理结果:
var apiResponse = await _requestProvider.PutAsync(uri, profile, authToken); if (apiResponse.IsSuccess) { var updatedProfile = apiResponse.SuccessResult; // 执行成功逻辑 } else { var errorDetails = apiResponse.ErrorResult; // 弹出错误提示,如显示errorDetails.Detail或errorDetails.Title }
修改方案二:使用Try模式(返回布尔值+输出参数)
如果不想新增包装类,可采用Try模式:
public async Task<bool> TryPutAsync<TResult>(string uri, TResult data, out TResult successResult, out ProblemDetailsWithErrors errorResult, string token = "", string header = "") { successResult = default; errorResult = default; HttpClient httpClient = GetOrCreateHttpClient(token); if (!string.IsNullOrEmpty(header)) { RequestProvider.AddHeaderParameter(httpClient, header); } var content = new StringContent(JsonSerializer.Serialize(data)); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); HttpResponseMessage response = await httpClient.PutAsync(uri, content).ConfigureAwait(false); try { await RequestProvider.HandleResponse(response).ConfigureAwait(false); successResult = await response.Content.ReadFromJsonAsync<TResult>(); return true; } catch (Exception) { errorResult = await response.Content.ReadFromJsonAsync<ProblemDetailsWithErrors>(); return false; } }
调用方式:
bool isSuccess = await _requestProvider.TryPutAsync(uri, profile, out var updatedProfile, out var errorDetails, authToken); if (isSuccess) { // 处理成功逻辑 } else { // 处理错误提示 }
注意事项
- 原
RequestProvider.HandleResponse方法通常会在响应状态码非2xx时抛出异常,因此通过捕获异常来序列化错误响应;如果该方法返回布尔值而非抛出异常,可直接用条件判断替代try-catch。 - 确保
ProblemDetailsWithErrors的属性名与API返回的ProblemDetails JSON字段完全匹配,避免序列化失败。
内容的提问来源于stack exchange,提问作者BryanCass
相关产品推荐
相关产品推荐

