Odata V4客户端如何处理异常?

How to handle exceptions in Odata V4 client?

Asp.Net Web API Odata 控制器操作:

public async Task<IHttpActionResult> Post(Product product)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    db.Products.Add(product);
    await db.SaveChangesAsync();
    return Created(product);
}

Odata客户端代码: (Odata v4 客户端代码生成器 v4)

static void AddProduct(Default.Container container, ProductService.Models.Product product)
{
    container.AddToProducts(product);
    var serviceResponse = container.SaveChanges();
    foreach (var operationResponse in serviceResponse)
    {
        Console.WriteLine("Response: {0}", operationResponse.StatusCode);
    }
}

我想在 AddProducts() 方法中以适当的方式处理异常,同时保存更改。

如何捕获处理从服务器 return BadRequest(ModelState); 发送的 ModelState 错误?

最后,我只想向最终用户显示从服务器发送的错误消息。 例子: "Product category is required."

ODataExceptionclass有什么用?这对我有帮助吗?

请帮帮我。

如果我理解得很好,你想拦截 ModelState 无效,并自定义显示给用户的 OData 错误。

如果你只是想让无效模型的错误出现在returned payload中,你可以使用:

if (!ModelState.IsValid)
{
    return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}

如果您想完全控制异常处理和显示的消息,我建议您采取几个操作要点来完成此操作:

  • 拦截 ModelState 无效:您可以使用自定义 ActionFilterAttribute 来做到这一点。在那里,您可以覆盖方法 OnActionExecuting(HttpActionContext actionContext)。您可以通过 actionContext.ModelState 访问 ModelState,检查它是否有效,检查有错误的字段,检查这些错误的性质以及为这些错误生成的消息等。ModelState 可能不是由于不同的原因而有效,例如与预期不同的类型、不满足 DataAnnotations 指定的要求等。您可以在 here 中查看有关模型验证的更多信息。对于您的情况,我猜 Product 实体将在 Category 字段中有一个 Required 数据注释。

    检查完所有错误后,您可以抛出包含 error/list 个错误和您想要的消息的自定义异常。这对于稍后拦截您的自定义异常并能够 return 您在错误负载中的自定义消息是必要的。

  • 拦截您的自定义异常: 创建一个自定义 ExceptionFilterAttribute 来拦截您抛出的异常。重写 OnException(HttpActionExecutedContext filterContext) 您将有权访问该异常,并检查它您将能够构建您正确的 OdataError:

    在这里你应该 return HttpResponseMessage 带有 BadRequest http 状态代码和创建的 ODataError 作为负载。作为一个非常简单的代码示例(您可以看到这取决于您如何构建自定义异常):

    public override void OnException(HttpActionExecutedContext filterContext)
    {
        Exception ex = filterContext.Exception;
        HttpRequestMessage currentRequest = filterContext.Request;
        if (filterContext.Exception.GetType() == typeof(YourCustomValidationException))
        {
            var oDataError = new ODataError()
            {
                ErrorCode = "invalidModel",
                Message = "Your model is not valid.",
                InnerError = new ODataInnerError()
                {
                    TypeName = ex.TheEntityThatHasErrors
                },
            };

    foreach (var validationError in ex.ValidationErrors) { oDataError.InnerError.Message += validationError + ", "; } HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.BadRequest); response.RequestMessage = currentRequest; response.Content = new StringContent(JsonConvert.SerializeObject(oDataError)); filterContext.Response = response; } }
  • 最后,您必须设置自定义 ActionFilterAttribute 和自定义 ErrorFilterAttribute,以便在每次请求到达您的控制器时使用。您可以装饰您的操作、控制器,或者您可以为 WebApiConfig 中的所有 API 控制器设置过滤器,其中 config.Filters.Add(...);

您可以在 here 中找到有关所有这些的更多信息。最后,错误和异常处理对于 ASP.Net Web API 来说是一样的,不管有没有 OData;不同之处在于,如果您有 OData API,您应该 return OData 样式错误。

希望所有这些信息都是可以理解的,并能以某种方式帮助您。