【问题标题】:Wcf (400) Bad Request when object properties are incorrect对象属性不正确时的 Wcf (400) 错误请求
【发布时间】:2014-04-07 13:14:18
【问题描述】:

我有一个 Wcf(启用 ajax)服务,它接受方法调用的对象。我的 Wcf 方法如下所示;

[OperationContract]
[XmlSerializerFormat]
[WebInvoke(Method = "POST", UriTemplate = "/XML/GetTypes", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml)]
XElement XMLGetTypes(TypeRequest TypeRequest)
{
    return Utilities.Convert.ObjectToXElement(TypeRequest.Execute(TypeRequest));
}

'TypeRequest'对象如下;

public class
{
    public int Id {get;set;}
    public string Name {get; set;}
}

我遇到的问题是,如果我使用请求对象中的无效数据调用该方法,例如;

<TypeRequest>
<Id>abc</Id>
<Name>Joe King</Name>
</TypeRequest>

如您所见,Id 应该是一个整数,但它是作为字符串传递的。这会导致来自 Wcf 服务的错​​误请求 400 响应。

理想情况下,我想处理错误并返回合适的响应。例如,我想返回包含错误信息的 JSON 或 XML 响应。

这可能吗?

【问题讨论】:

  • 您从 WCF 得到的错误是什么?
  • System.Net.WebException:远程服务器返回错误:(400)错误请求,因为请求传递的是字符串而不是整数

标签: c# wcf response


【解决方案1】:

IIS 允许您在管道中创建错误处理程序。如何处理代码以及返回什么取决于您自己,不过我会小心,因为这会处理 IIS 应用程序的所有错误。

public class ErrorHttpHandler : IHttpHandler
    {
        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            if (context.Request.QueryString.Count == 0)
                return;

            string strStatusCode = context.Request.QueryString[0].Split(';').FirstOrDefault() ?? "500";
            int statusCode = 500;
            int.TryParse(strStatusCode, out statusCode);

            string message = "Unhandled server error.";

            switch (statusCode)
            {
                case 400:
                    message = "Bad request.";
                    break;

                case 404:
                    message = "Item not found.";
                    break;
            }

            context.Response.StatusCode = statusCode;
            context.Response.Write(string.Format("<Error><Message>{0}</Message></Error>", message));
        }
    }

并在您的 web.config 中,为要调用的处理程序添加以下代码:

<system.webServer>
    <httpErrors errorMode="Custom">
      <clear/> 
      <error statusCode="404" path="/application/ErrorHandler" responseMode="ExecuteURL"/>
      <error statusCode="400" path="/application/ErrorHandler" responseMode="ExecuteURL"/>
    </httpErrors>
    <handlers>
      <add name="ErrorHandler" path="ErrorHandler" verb="*" type="Your Application.ErrorHttpHandler, FrameworkAssembly"/>
    </handlers>
  </system.webServer>

所有这些都来自this site。

【讨论】:

    【解决方案2】:

    您可以使用参数检查器检查您的参数,这将允许您使用所需的消息抛出错误异常。您还可以为您的客户端(如果它是 .net 客户端)提供参数检查器属性。因此,在通过验证之前不会发送消息,这可以节省您的流量。这是一个链接: WCF Parameter Validation with Interceptor

    如果您的客户向您发送错误信息。您必须使用消息检查器: MSDN, Logging all WCF messages

    这里有一个更好的例子: http://msdn.microsoft.com/en-us/library/ff647820.aspx

    您必须更多地关注 AfterReceiveRequest 方法。请注意,需要创建消息的缓冲副本,然后处理消息的一个副本,然后返回另一个副本。

    【讨论】:

      【解决方案3】:

      可以这样做,但你可能需要做一些不同的事情,最简单的方法可能是改变你传入的类型请求,如下所示

      public IncomingClass
      {
          public string Id {get;set;}
          public string Name {get; set;}
      }
      

      这意味着传入的数据是有效的,你不会得到错误400,

      然后您可以使用

      进行验证
      int myId = incomingClass.Id as int;
      
      if (myId == null)
      {
      //put suitable error handling here
      }
      

      或者最好还是将整个函数放在一个 try catch 循环中,并以这种方式处理错误。我认为您会在输入函数之前发现错误正在发生。您的 WCF 服务需要可转换为对象“TypeRequest”类型的 xml,但您的 xml 无效。

      希望有帮助

      【讨论】:

      • 有没有更好的解决方案?
      • 据我所知,没有办法将不符合服务预期属性的对象接受到服务中,这意味着在您有机会进行任何验证之前您的方法服务已创建错误。
      • int 不是可以为空的类型,使用 as 运算符进行强制转换不会编译。无论如何,它不能通过类型转换转换为字符串。您需要使用 Convert.ToInt32() 之类的东西,并在异常失败时捕获异常。
      • @JamesT 我遇到的问题是这是一个示例对象。我有很多对象,所以使用转换之类的东西不是一个好的解决方案
      • 我猜你也可以做 int.tryParse(string)
      【解决方案4】:

      我认为您需要一些方法拦截器并在其中编写预期的逻辑。

      这里有一个很好的资源http://msdn.microsoft.com/en-us/magazine/cc163302.aspx

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-09
        • 2011-04-08
        • 2012-04-27
        • 2015-10-15
        • 2015-11-24
        相关资源
        最近更新 更多