【问题标题】:ASP.net WebApi - Custom Message for malformed post dataASP.net WebApi - 格式错误的帖子数据的自定义消息
【发布时间】:2012-08-16 14:17:29
【问题描述】:

我有一个 MVC 4 WebAPI 应用程序。我想要做的是过滤掉任何ModelState 由于在放置/发布期间发送的格式错误的数据而发生的错误。

我有一个ActionFilterAttribute 来检查ModelState 是否有效。我想将状态的ErrorMessages 发送回给用户。这部分工作正常。

/// <summary>
/// This filter will validate the models that are used in the webapi
/// </summary>
public class MyValidationFilter :System.Web.Http.Filters.ActionFilterAttribute
{
    public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        if (!actionContext.ModelState.IsValid)
        {
            //ErrorResponse is just a simple data structure used to hold response
            ErrorResponse errorResponse = new ErrorResponse();

            //loop through each key(field) and see if it has any errors
            foreach (var key in actionContext.ModelState.Keys)
            {
                var state = actionContext.ModelState[key];
                if (state.Errors.Any())
                {
                    string validationMessage = state.Errors.First().ErrorMessage;
                    errorResponse.ErrorMessages.Add(new ErrorMessage(validationMessage));                      
                }
            }

            //this is a custom exception class that i have that sends the response to the user.
            throw new WebAPIException(HttpStatusCode.BadRequest, errorResponse );

        }

    }
}

普通验证(必需、StringLength、Regex)都可以正常工作,因为我可以控制这些消息。

[Required(ErrorMessage = "ID is required")]
public string ID { get; set; }

但是,如果有人传递了格式不正确的 XML 或 JSON 数据,我将无法控制消息。如果发生这种情况,那么我可能会得到

未终止的字符串。预期分隔符:\"。路径 '',第 1 行,位置 9.

解析属性名称后出现无效字符。预期':'但得到: }。路径 '',第 1 行,第 9 位。

或者这些显示我的命名空间。

将值 \"Medium\" 转换为类型时出错 'MyNameSpace.Tenant.WebAPIs.Library.IndividualRegistrationInfo'。小路 '',第 1 行,第 8 位。

第 1 行位置 7 出错。需要元素 命名空间中的“IndividualRegistrationInfo” 'http://schemas.datacontract.org/2004/07/MyNameSpace.Tenant.WebAPIs.Library.IndividualRegistrationInfo'.. 遇到名为“asdf”、命名空间“”的“元素”

当这种情况发生时,我想以某种方式发回一个通用的“无效数据”消息。是否有另一个我可以使用的过滤器,或者其他可以捕获和覆盖这些消息的地方?

更新

根据 Chris 的建议,我最终做了以下事情:

我为 JSON 和 XML 创建了 2 个新的格式化程序。

public class JsonFormatter : JsonMediaTypeFormatter
{
    public override System.Threading.Tasks.Task<object> ReadFromStreamAsync(Type type, System.IO.Stream stream, System.Net.Http.Headers.HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
    {

       System.Threading.Tasks.Task<object> task = base.ReadFromStreamAsync(type, stream, contentHeaders, formatterLogger);

        //parse error if null
       if (task.Result == null)
       {
           //handle error here.
       }

       return task;
    }
}


public class XMLFormatter : XmlMediaTypeFormatter
{
    public override System.Threading.Tasks.Task<object> ReadFromStreamAsync(Type type, System.IO.Stream stream, System.Net.Http.Headers.HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
    {

        System.Threading.Tasks.Task<object> task = base.ReadFromStreamAsync(type, stream, contentHeaders, formatterLogger);

        //parse error if null
        if (task.Result == null)
        {
            //handle error here
        }

        return task;
    }
}

在 global.asax 的 Application_Start 方法中

GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonFormatter());
GlobalConfiguration.Configuration.Formatters.Insert(1, new XMLFormatter());

我不确定是否有更好的方法,但这似乎可行。

【问题讨论】:

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


    【解决方案1】:

    我不完全确定,但您可能只是重载默认的 JsonMediaTypeFormatterXmlMediaTypeFormatter 实现,并用您自己的异常包装它们的异常。这样做的好处是将您的异常处理直接与问题的根源(即格式化程序)联系起来,而不是尝试通过IExceptionFilter 来处理它。

    【讨论】:

    • 我无法直接了解正在发生的错误,但我确实创建了自己的格式化程序。我能够判断何时存在格式错误的数据,但可能有更好的方法。
    【解决方案2】:

    这是我根据 Chris 的建议最终做的事情:

    为 JSON 和 XML 创建了 2 个新的格式化程序。

    public class JsonFormatter : JsonMediaTypeFormatter{
    public override System.Threading.Tasks.Task<object> ReadFromStreamAsync(Type type, System.IO.Stream stream, System.Net.Http.Headers.HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
    {
    
       System.Threading.Tasks.Task<object> task = base.ReadFromStreamAsync(type, stream, contentHeaders, formatterLogger);
    
        //parse error if null
       if (task.Result == null)
       {
           //handle error here.
       }
    
       return task;
    }}
    
    
    
    public class XMLFormatter : XmlMediaTypeFormatter
    {
        public override System.Threading.Tasks.Task ReadFromStreamAsync(Type type, System.IO.Stream stream, System.Net.Http.Headers.HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
        {
    
            System.Threading.Tasks.Task task = base.ReadFromStreamAsync(type, stream, contentHeaders, formatterLogger);
    
            //parse error if null
            if (task.Result == null)
            {
                //handle error here
            }
    
            return task;
        }
    }
    
    

    在 global.asax 的 Application_Start 方法中

    
    GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonFormatter());
    GlobalConfiguration.Configuration.Formatters.Insert(1, new XMLFormatter());
    

    我不确定是否有更好的方法,但这似乎可行。

    【讨论】:

      【解决方案3】:

      问题来了:

      1. MediaTypeFormatter 使用与 HTTP 请求关联的 System.IO.Stream
      2. 虽然该格式化程序将调用 IFormatterLogger.OnError(string,Exception),但第一个参数只是一个“路径”(无论解析器选择如何构想它),而不是输入本身的副本。

      所以是的,如果您想查看和响应(或记录)导致错误的请求,您需要实现并注册自己的 MediaTypeFormatter,进行自己的解析/反序列化,并根据到您自己的协议(除了 WebApi 协议)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-29
        • 1970-01-01
        • 2017-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-22
        • 2012-07-06
        相关资源
        最近更新 更多