如何使用WCF服务生成XML输出?

时间:2012-11-12 14:33:06

标签: c# wcf web-services

我已经设置了以下界面。

[ServiceContract]
public interface IService1
{
  [OperationContract]
  String Ping();
}

其实施如下。

public class Service1 : IService1
{
  public string Ping(){ return "Pong"; }
}

根据VS中的测试应用程序,它在调用时正常工作。我的问题是当我输入 http:// localhost:12345 / Service1.svc (或者可能是 Service1.svc?Ping 或 Service.svc / Ping )。它是完全关闭还是我在正确的树上吠叫?

当然,“ Pong ”最终将成为XML结构。

修改

@carlosfigueira在回复中提供的设置为解决方案的建议提供了一个很好的结构,但不幸的是,当我使用F5运行时,我的机器上会出现错误消息。似乎元数据是必需的,端点也是如此。

2 个答案:

答案 0 :(得分:8)

我终于得到了完全的PO,并开始与商业联系。这就是我制作的 - 它可以在我的机器上运行,我希望它不是一个本地现象。 :)

IRestService.cs - 声明,您的代码向联系客户承诺的内容

[ServiceContract]
public interface IRestService
{
  [OperationContract]
  [WebInvoke(Method = "GET", 
    ResponseFormat = WebMessageFormat.Xml, 
    BodyStyle = WebMessageBodyStyle.Wrapped, 
    UriTemplate = "xml/{id}")]
  String XmlData(String id);

  [OperationContract]
  [WebInvoke(Method = "GET", 
    ResponseFormat = WebMessageFormat.Json, 
    BodyStyle = WebMessageBodyStyle.Wrapped, 
    UriTemplate = "json/{id}")]
  String JsonData(String id);
}

RestService.svc.cs - 实现,您的代码实际对客户端做了什么

public class RestService : IRestService
{
  public String XmlData(String id)
  {
    return "Requested XML of id " + id;
  }

  public String JsonData(String id)
  {
    return "Requested JSON of id " + id;
  }
}

Web.config - 配置,代码在客户端的路上处理的内容

<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>

  <system.serviceModel>
    <services>
      ...
    </services>
    <behaviors>
    </behaviors>
  </system.serviceModel>

</configuration>

services - 描述服务性质的标签内容

<service name="DemoRest.RestService" 
         behaviorConfiguration="ServiceBehavior">
  <endpoint address="" binding="webHttpBinding" 
            contract="DemoRest.IRestService" 
            behaviorConfiguration="web"></endpoint>
</service>

行为 - 描述服务行为和终点的标签内容

<serviceBehaviors>
  <behavior name="ServiceBehavior">
    <serviceMetadata httpGetEnabled="true"/>
    <serviceDebug includeExceptionDetailInFaults="true"/>
  </behavior>
</serviceBehaviors>

<endpointBehaviors>
  <behavior name="web">
    <webHttp/>
  </behavior>
</endpointBehaviors>

Index.html - 执行者,您的代码可以被称为

<html>
  <head>
    <script>
      ...
    </script>
    <style>
      ...
    </style>
  </head>
  <body>
    ...
  </body>
</html>

script - 描述JavaScript中可执行文件的标记内容

window.onload = function () {
  document.getElementById("xhr").onclick = function () {
    var xhr = new XMLHttpRequest();
    xhr.onload = function () { alert(xhr.responseText); }
    xhr.open("GET", "RestService.svc/xml/Viltersten");
    xhr.send();
  }
}

style - 描述外观的标签内容

.clickable
{
  text-decoration: underline;
  color: #0000ff;
}

body - 描述标记结构的标记内容

<ul>
  <li>XML output <a href="RestService.svc/xml/123">
    <span class="clickable">here</span></a></li>
  <li>JSON output <a href="RestService.svc/json/123">
    <span class="clickable">here</span></a></li>
  <li>XHR output <span id="xhr" class="clickable">here</span></li>

所有内容都存储在名为DemoRest的项目中。我创建了自己的文件来声明和实现服务,删除默认的文件。出于空间原因,省略了using的指令以及XML版本声明。

现在可以使用以下URL检索响应。

localhost:12345/RestService.svc/xml/Konrad
localhost:12345/RestService.svc/json/Viltersten
  1. 是否有其他人也可以上班?
  2. 有关改进或澄清的任何建议吗?

答案 1 :(得分:1)

如果您将服务端点定义为WebHttp端点(a.k.a. REST端点),您将获得所需的服务。最简单的方法是在svc文件中使用WebServiceHostFactory

Service1.svc。

<%@ ServiceHost Language="C#" Debug="true" Service="YourNamespace.Service1"
                Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

或者您可以在没有工厂的情况下定义端点,方法是定义它将使用webHttpBinding并具有<webHttp/>行为:

<system.serviceModel>
  <behaviors>
    <endpointBehaviors>
      <behavior name="MyBehavior">
        <webHttp/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <services>
    <service name="YourNamespace.Service1">
      <endpoint address=""
                behaviorConfiguration="MyBehavior"
                binding="webHttpBinding"
                contract="YourNamespace.IService1" />
    </service>
  </services>
</system.serviceModel>

更新:由于有些人遇到了问题,我写了一个使用XMLHttpRequest与上面列出的服务进行通信的完整示例。代码可以在https://github.com/carlosfigueira/WCFQuickSamples/tree/master/WCFForums/QuickWebCode1找到(查找StackOverflow_13345557),它主要列在这里。

服务代码(请注意我使用JSON作为响应,但XML也可以正常工作):

namespace StackOverflow_13345557
{
    [ServiceContract]
    public interface IService1
    {
        [WebGet(ResponseFormat = WebMessageFormat.Json)]
        string Ping();
        [WebGet(ResponseFormat = WebMessageFormat.Json)]
        string PingWithParameters(int a, string b);
    }

    public class Service1 : IService1
    {
        public string Ping()
        {
            return "Hello";
        }

        public string PingWithParameters(int a, string b)
        {
            return string.Format("Hello {0} - {1}", a, b);
        }
    }
}

.SVC文件 - 请注意不使用Factory属性,因为我是通过配置定义端点的:

<%@ ServiceHost Language="C#" Debug="true" Service="StackOverflow_13345557.Service1"
                CodeBehind="StackOverflow_13345557.svc.cs" %>

<强>的web.config

<system.serviceModel>
  <services>
    <service name="StackOverflow_13345557.Service1">
      <endpoint address=""
                behaviorConfiguration="WithWebHttp"
                binding="webHttpBinding"
                bindingConfiguration="WithJSONP"
                contract="StackOverflow_13345557.IService1" />
    </service>
  </services>
  <behaviors>
    <endpointBehaviors>
      <behavior name="WithWebHttp">
        <webHttp/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <bindings>
    <webHttpBinding>
      <binding name="WithJSONP" crossDomainScriptAccessEnabled="true" />
    </webHttpBinding>
  </bindings>
</system.serviceModel>

HTML页面访问服务(仅限正文):

<body>
    <script type="text/javascript">
        function StackOverflow_13345557_Test(passParameters) {
            var baseUrl = "/StackOverflow_13345557.svc";
            var cacheBuster = new Date().getTime(); // to prevent cached response; development only
            var url;
            if (passParameters) {
                url = baseUrl + "/PingWithParameters?a=123&b=john+doe&_=" + cacheBuster;
            } else {
                url = baseUrl + "/Ping?_=" + cacheBuster;
            }
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4) {
                    document.getElementById("result").innerText = xhr.responseText;
                }
            }

            xhr.open('GET', url, true);
            xhr.send();
        }
    </script>
    <input type="button" value="StackOverflow 13345557 (no params)" onclick="StackOverflow_13345557_Test(false);" /><br />
    <input type="button" value="StackOverflow 13345557 (with params)" onclick="StackOverflow_13345557_Test(true);" /><br />
    <div id='result'></div>
</body>

又一次更新:在https://skydrive.live.com/redir?resid=99984BBBEC66D789!6355添加了一个包含上述代码的自包含最小项目。