【问题标题】:Model validation in Web API - Exception is thrown with out a throw statement?Web API 中的模型验证 - 在没有 throw 语句的情况下抛出异常?
【发布时间】:2014-06-11 09:42:37
【问题描述】:

我从here 看到了model validation(下部分:Handling Validation Errors)。

code-sn-p 如下Web API

public class ValidateModel : ActionFilterAttribute
    {
        public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            if (actionContext.ModelState.IsValid == false)
            {
                actionContext.Response = actionContext.Request.CreateErrorResponse(
                    HttpStatusCode.BadRequest, actionContext.ModelState);
            }

            base.OnActionExecuting(actionContext);
        }
    }

问题是upon validation of model,如果有任何错误,it assigns an model state invalid异常。

然后,在进入实际方法(用这个[ValidateModel] 属性修饰)之前,WebAPI 只返回一个 400 请求。

但是怎么做呢?哪个函数返回HTTP 400

这个方法执行完成后会发生什么?控制流向哪里?

编辑:

我应用这个属性的动作是正常的。

[ValidateModel]
public IHttpActionResult Post([FromBody]Request)
{
//do normal business logics here.
return Ok(SuccessMessage);
}

【问题讨论】:

  • 可能与名为 CreateErrorResponse 的方法有关。听起来可能会产生错误响应
  • 1) 使用 try..catch 并捕获错误,正如 Daveparsons 所说,它可能是 CreateErrorResponse 函数。 2) 是否有为此触发的过滤器?
  • @Zakos:不,它根本不会抛出任何错误。我删除了actionContext.Response,以便调用CreateErrorResponse。但它返回一个200
  • @DaveParsons: try catch 没有捕捉到异常。控制只是顺流而下。
  • 这就是 Web Api 的工作原理。这就是 Web Api 的设计和架构。当您将值设置为 actionContext.Response 时,在此示例中您将其设置为 BadRequest ,即 400,这是服务器的答案。 200 是服务器的 OK 回答。并且当 actionContext.Response 被设置时,它不会向前移动到控制器,请求就完成了!现在,当您说“抛出”时,我们会自动处理错误、异常,但情况并非如此。所以请注意。这里没有错误/异常。您的代码说:如果模型无效 - 回答 400 ,否则继续。

标签: c# asp.net .net asp.net-web-api asp.net-web-api2


【解决方案1】:

要了解控制流程,您首先需要访问此链接 -

Action Attribute Class Reference

检查那里的方法部分。如果明确指出,OnActionExecuting 在执行带有此属性的特定操作之前执行,OnActionExecuted 在执行完成后执行。由于您正在像这样实施OnActionExecuting -

public class ValidateModel : ActionFilterAttribute
{
    public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        if (actionContext.ModelState.IsValid == false)
        {
            actionContext.Response = actionContext.Request.CreateErrorResponse(
                HttpStatusCode.BadRequest, actionContext.ModelState);
        }

        base.OnActionExecuting(actionContext);
    }
}

因为错误是在这个方法内部抛出的,像这样 -

 if (actionContext.ModelState.IsValid == false)
        {
            actionContext.Response = actionContext.Request.CreateErrorResponse(
                HttpStatusCode.BadRequest, actionContext.ModelState);
        }

只有当OnActionExecuting 方法找到有效模型时,您的方法才会执行。从错误 400 看来,您当前的模型状态似乎无效,因此它无法成功,除非您提供有效的模型,否则您的方法将永远不会被执行。在这个方法里面设置一个调试点,你可以找出它失败的原因。

顺便说一句,异常不会被抛出,它只是一个标准响应,由 -

base.OnActionExecuting(actionContext);

http://msdn.microsoft.com/en-us/library/system.web.mvc.actionfilterattribute(v=vs.118).aspx

【讨论】:

    【解决方案2】:

    要查找错误点,只需在 Global.asax 中的 Application_Error 上创建一个断点,然后按照错误详细信息和堆栈跟踪找到相同的来源。

    【讨论】:

      【解决方案3】:

      当调用方法 OnActionExecuting 时,它会检查模型是否有效。如果模型无效 actionContext.Response 将调用服务器,该服务器将返回 400 代码,这意味着它是错误的请求。 这完全取决于您如何调用此 Web api。通常,您可以从 asp.net 获得 jquery 或其他一些库或代码,使用适当的对象调用 webapi。首先检查该对象是否有效。如果它是有效的,它将继续处理任何东西都不会返回。如果对象状态无效,则返回状态码 400。如果返回 200,则表示您的对象有效并且 web api 已执行并返回 200。此 200 不是从 webapi 返回,而是在写入数据后从 EF 返回成功。 如果您想使用 try catch 块,则不需要检查模型是否有效。只需通过带有对象的 url 并等待响应而不是捕获并显示。

      【讨论】:

        【解决方案4】:

        如果您的 Request 数据类型定义为 structabstract class,则无法实例化,这可能是可能的原因。如果是结构,则直接设置为Nullable,如果是抽象类或interface,则可以创建自己的ModelBinder 来处理创建,也可以通过具体实现来更改它。

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-07
        • 2022-08-19
        • 1970-01-01
        • 2015-07-11
        • 1970-01-01
        • 2015-11-14
        • 2015-05-01
        • 1970-01-01
        相关资源
        最近更新 更多