使用 JSONP 和 SOAP 端点调用 WCF 服务
一个简单的应用程序,使用 jQuery/JSONP 和 XML/SOAP 实现来消费 WCF 服务。
介绍
几个月前,我开始研究从 Web 服务消费 JSON 对象的一些功能。我决定实现 WCF 来测试与 JSON 数据的良好集成。
Gary Stafford 杰出的文章 帮助我配置了第一个跨域 JSON 应用程序,该应用程序消费 REST/JSONP WCF 服务。这包括在服务中设置跨域“JSONP 终结点”。
该示例满足了一部分需求,但为了配置相同的 WCF 服务以通过常规的服务引用 SOAP 代理进行消费,我花了一周的时间进行研究。在此阶段,我需要第二个“终结点”配置。
背景
首先请记住,JSONP 或“带填充的 JSON”是对 JSON 数据格式的补充。它用于从部署在不同域中的服务器请求数据,这被许多 Web 浏览器禁止。
WCF 服务用于企业应用程序开发。除许多优点外,WCF 还可以在同一服务上提供多个终结点(HTTP、TCP 等)。
通过配置具有 JSONP 和 SOAP 终结点的 WCF 服务,您可以使其可供不同类型的客户端访问。这对于能够消费 WCF 代理的客户端以及进行 JSONP 数据 HTTP 通信的客户端很有用。
REST(Representational State Transfer,表述性状态转移)以几种纯文本格式提供来自服务的直接响应。如果 WCF 服务使用的是 REST/JSONP,那么客户端就不需要消费 WCF 服务代理了。
REST/JSONP 在需要 JSON 数据来处理前端显示的 Ajax 应用程序中性能非常重要。现在,只需通过简单的 HTTP 通信即可获取该数据。
示例
此示例基本上是一个服务器应用程序 MyService
,它运行一个 WCF 服务,该服务具有两个不同的终结点供 Web 客户端应用程序 MyClient
消费。
- SOAP 终结点从客户端方法
loadDropDownSOAP()
使用,该方法填充 ASP 下拉列表服务器控件。 - 第二个 REST/JSONP 终结点也由 JavaScript 方法
loadDropDownJSONP()
使用,该方法尝试填充另一个下拉列表。这次,该方法只需要一次 HTTP 调用即可从服务中获取数据。
客户端应用程序的外观和感觉非常简单。只需点击“使用 JSONP 调用加载”和“使用 SOAP 调用加载”即可启动这两个操作。
使用代码
zip 文件夹包含在 Visual Studio 2010(框架 4.0)中实现的两个网站应用程序。MyService
和 MyClient
已准备好在本地环境中进行编译和测试:
MyClient
。您可以构建并运行该应用程序。客户端应用程序将在 https://:7726/ 上执行。MyService
。也已准备好执行。该服务将在 https://:6573/Service.svc 上运行。
下面您可以阅读有关最相关文件的更多实现细节。
MyService - Web.config
请查看终结点和绑定配置。SOAP 请求将需要处理 address="soap"
终结点设置。
对于 REST/JSONP 终结点,重要的是使用 binding="webHttpBinding"
;对于 SOAP 终结点,则使用 binding="basicHttpBinding"
。
<?xml version="1.0"?>
<configuration>
<appSettings>
</appSettings>
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="false" />
<services>
<service behaviorConfiguration="WebServiceBehavior" name="MyService.Service">
<endpoint address="" behaviorConfiguration="jsonBehavior" binding="webHttpBinding"
bindingConfiguration="webHttpBindingWithJsonP" contract="MyService.IService" />
<endpoint address="soap" binding="basicHttpBinding" contract="MyService.IService" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="WebServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="webHttpBindingWithJsonP"
crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
</system.serviceModel>
<system.web>
<compilation debug="false" targetFramework="4.0" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
MyService - Iservice.cs(服务合同)
响应的格式在两个操作合同中都已设置。可以是 WebMessageFormat.Json
或 WebMessageFormat.Xml
。
[ServiceContract]
public interface IService
{
[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/GetTourListJSONP/")]
cTourList GetTourListJSONP();
[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml,
UriTemplate = "/GetTourListXML/")]
cTourList GetTourListXML();
}
MyService - Service.scv.cs(IService 接口的实现)
两个服务方法都返回一个基于 cTour
对象集合实现的 tours 列表,该列表包含在 cTourList
类中。
public class Service : IService
{
public cTourList GetTourListJSONP()
{
return CreateTourList();
}
public cTourList GetTourListXML()
{
return CreateTourList();
}
private cTourList CreateTourList()
{
cTourList oTourList = new cTourList();
oTourList.Add(new cTour() { ID = 1, description = "Barcelona" });
oTourList.Add(new cTour() { ID = 2, description = "Paris" });
oTourList.Add(new cTour() { ID = 3, description = "Rome" });
oTourList.Add(new cTour() { ID = 4, description = "London" });
oTourList.Add(new cTour() { ID = 5, description = "Moscow" });
return oTourList;
}
}
一旦服务在 Visual Studio 中运行,就可以使用 WCF 测试客户端测试两个终结点。建议在最终使用客户端应用程序之前进行此操作。
MyClient - Web.config
来自客户端应用程序的 SOAP 调用需要在项目中进行服务引用设置。您可以通过打开 Visual Studio 2010 -> Project -> Add Service Reference 来进行处理。
添加服务引用后,请确保“address”的“soap”文本包含在终结点中:address="https://:6573/Service.svc/soap"。否则,SOAP 调用将不成功。
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="false" targetFramework="4.0" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://:6573/Service.svc/soap" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService" contract="WCFReference.IService"
name="BasicHttpBinding_IService" />
</client>
</system.serviceModel>
</configuration>
MyClient - Default.aspx.cs
方法 loadDropDownSOAP()
使用我们上面注释的 SOAP 终结点。调用返回一个在 WCFReference.cTourList
中实现的结构。
public partial class _Default : System.Web.UI.Page
{
protected void Button1_Click(object sender, EventArgs e)
{
// sets dropdown list empty
DropDownListSOAP.Items.Clear();
loadDropDownSOAP();
}
private void loadDropDownSOAP()
{
// XML-SOAP CALL TO WCF SERVICE
WCFReference.ServiceClient oWebservice = new WCFReference.ServiceClient();
WCFReference.cTourList oTourList = oWebservice.GetTourListXML();
foreach (WCFReference.cTour oTour in oTourList)
{
DropDownListSOAP.Items.Add(new ListItem(oTour.description, Convert.ToString(oTour.ID)));
}
}
}
MyClient - Scripts/base.js
此文件包含 $.ajax
调用,该调用将使用 WCF 服务上配置的一个特定终结点以 REST/JSONP 模式从 WCF 服务检索数据。变量 wcfServiceUrl
包含服务的默认 HTTP 地址。
请注意,JavaScript 方法使用 jQuery 填充下拉列表。$.ajax
调用返回包含在 jsonpCallback: "tourList"
结构中的 tours 列表。
var wcfServiceUrl, populateDropdown;
// default URL WCF service
wcfServiceUrl = "https://:6573/Service.svc/";
populateDropdown = function () {
var ID, description;
ID = this.ID;
description = this.description;
$("#selectJSON")
.append($("<option></option>")
.val(ID)
.html(description));
};
function loadDropDownJSONP(idDropdownJson, idDropdownSoap) {
// sets both dropdown lists empty
$("#" + idDropdownSoap + "").html("");
$("#" + idDropdownJson + "").html("");
// JSONP CALL TO WCF SERVICE
$.ajax({
cache: false,
url: wcfServiceUrl + "GetTourListJSONP",
data: "{}",
type: "GET",
jsonpCallback: "tourList",
contentType: "application/javascript",
dataType: "jsonp",
error: function () {
alert("list failed!");
},
success: function (list) {
$.each(list, populateDropdown); // must call function as var
}
});
}
历史
- 2012/04/26:文章初次发布。