RESTful WCF服务在发送"原始"XML时返回400代码

dpa*_*ons 7 c# rest wcf

我一直在用我的头撞墙两天,希望有人可以帮我一把.我所拥有的是使用WCF编写的RESTful Web服务; 实际上只有两个接受单个字符串参数并返回字符串的方法.参数和返回值都是直接的XML.

[ServiceContract]
public interface IService
{
    [OperationContract]
    [WebGet(UriTemplate = "/method1/{data}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Xml)]
    string Method1(string data);

    [OperationContract]
    [WebGet(UriTemplate = "/method2/{data}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Xml)]
    string Method2(string data);

}
Run Code Online (Sandbox Code Playgroud)

为了论证,我们可以说这两种方法的实现如下所示:

public string Method1(string data)
{
    return string.Format("You entered: {0}", data);
}
Run Code Online (Sandbox Code Playgroud)

如果我转到http://myuri.com/service.svc/method1/foo,则会向浏览器写入以下内容:

  <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">You 
    entered: foo</string> 
Run Code Online (Sandbox Code Playgroud)

这很好用,但如果我将网址更改为:http://myuri.com/service.svc/method1/ <foo>我收到400(错误请求).所以我使用以下代码启用了一些跟踪器以查看发生了什么:

<system.diagnostics>
<sources>
  <source name="System.ServiceModel"
          switchValue="All">
    <listeners>
      <add name="traceListener"
          type="System.Diagnostics.XmlWriterTraceListener"
          initializeData= "c:\Traces.svclog" />
    </listeners>
  </source>
</sources>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我使用切换值'All'来捕获在执行此服务期间发生的每个事件.我使用URL格式跑回了几次,这种格式可以验证跟踪器是否正常工作.然后我转到包含XML标记foo的URL并按预期收到400错误,但是当我回到日志文件时,没有附加信息附加到它的末尾.这使我相信在调用WCF服务之前显示400错误.

最后,我将方法从'GET'方法切换到'POST'方法,使用WebRequest/WebResponse写了一些具有相同结果的代码.现在我已经阅读了一些帖子,谈论在客户端使用XmlSerializer将数据发送到服务但是这违背了这项服务的目的.当我使用.NET编写服务时,很可能PHP或经典ASP脚本将连接到此服务,显然,他们无法访问XmlSerializer.

所以我的百万美元问题是:是否可以向WCF中开发的RESTful Web服务发送"原始"XML请求,如果是,如何?

PS进入和退出服务的XML不是基于任何有形对象,它只是我创建的用于此服务的结构.进入的XML通过XPath进行解析,将值放入更大的XML字符串中,并传递给外部API.该API的结果将被处理,然后由我的RESTful服务返回.

任何帮助将不胜感激!!

dpa*_*ons 3

布雷特,谢谢你的一些代码。不幸的是,我在这个线程中找到了它:涉及复杂类型的WCF Rest参数,并在发帖之前尝试过它。

无论如何,我已经解决了这个问题。现在我想说,我有一个完整的“尤里卡”时刻,一切都聚集在一起,但事实是我刚刚开始向 Google 扔首字母缩略词,其中一个 SERP 将我带到了这个链接:http:// blogs .msdn.com/pedram/archive/2008/04/21/how-to-consume-rest-services-with-wcf.aspx

该链接本身并没有直接解决当前的问题,但它让我对如何组合 URI 模板有了不同的思考。我读过这篇 MSDN 文章http://msdn.microsoft.com/en-us/library/dd203052.aspx关于如何组合 RESTful 服务。在示例中,作者提供了几种不同的模板,其中一些使用典型的查询字符串参数式模板,另一些则不使用。无论出于何种原因,我选择的模板都没有典型的查询字符串参数,如我的原始帖子中所示。所以我修改了我的代码并想出了这个:

[OperationContract] 
[WebGet(UriTemplate = "/method1/?xml={data}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Xml)] 
string Method2(string data); 
Run Code Online (Sandbox Code Playgroud)

请注意,URI 模板是唯一发生更改的内容;从“/method1/{data}”更改为“/method1/?xml={data}”。然后我导航到http://myuri.com/service.svc/method1/?xml=和 viola,一切都工作得很好!

这也是 POST 的问题。无论出于何种原因,在内容正文中传递 XML(即使作为键/值对)都会导致 400 错误。使用与上面显示的完全相同的 URI 模板,我打开 Fiddler,执行 POST,结果是 200 OK。

感谢大家的帮助。