65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Jquery/JavaScript 调用跨域 WCF 服务

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.74/5 (20投票s)

2011年7月11日

CPOL

5分钟阅读

viewsIcon

175344

downloadIcon

6304

使用 Jquery/JavaScript 调用跨域 WCF 服务

引言

本文介绍如何从您的页面调用跨域 WCF 服务,即调用托管在一个域上的 WCF 服务,而从托管在另一个域上的页面的 Jquery/JavaScript 进行调用。

但在开始之前,最好先了解一下服务器之间交换数据的格式。

JSONP - 带填充的 JSON

Ajax 允许在后台获取数据而不干扰显示。通过使用 XMLHttpRequest 对象进行的 Ajax 调用允许客户端 JavaScript 代码建立 HTTP 连接。
但是,由于浏览器的限制,Ajax 调用不允许获取跨域数据。当请求来自另一个域的数据时会发出安全错误。一种避免安全错误的方法是控制数据所在的位置的远程服务器,并且所有请求都转到同一个域。这就引出了一个问题,如果数据只来自自己的服务器,那有什么意义呢?如果需要从其他服务器获取数据该怎么办?

有一个方法可以克服这个限制 - 在网页中插入一个动态脚本元素,其源指向另一个域中的服务 URL,并在脚本本身中获取数据。当脚本加载时,它会执行。这是因为同源策略不会阻止动态脚本插入,并将脚本视为从提供网页的域加载的。但是,如果此脚本尝试从另一个域加载文档,它将失败。幸运的是,您可以通过添加 JavaScript 对象表示法 (JSON) 来改进此技术。

JSONP 或“带填充的 JSON”是基本 JSON 数据格式的补充,它是一种使用模式,允许页面从不同域的服务器请求数据。作为解决此问题的方法,JSONP 是较新的跨域资源共享 (Cross-Origin Resource Sharing) 方法的替代方案。

根据同源策略,从 server1.example.com 提供的网页通常无法连接或通信除 server1.example.com 之外的服务器。HTML <script> 元素是一个例外。利用 <script> 元素的开放策略,一些页面使用它们来检索从其他来源动态生成的 JSON 格式数据并对其进行操作的 JavaScript 代码。这种使用模式称为 JSONP。JSONP 请求检索的不是 JSON,而是任意 JavaScript 代码。它们由 JavaScript 解释器执行,而不是由 JSON 解析器解析。

调用跨域 WCF 服务

现在,在接下来的讨论中,我将向您展示如何轻松地从托管在其他域上的页面调用托管在其他域上的 WCF 服务。
以下是您应该先查看的文章列表,然后再继续

首先,创建一个新的解决方案,然后添加一个新项目,即 WCF 服务,并按照以下步骤操作。

步骤 1

在 .NET 4.0 的新版本中,WCF 开发团队增加了对 JSONP 的支持。新增了一个属性,通过将其设置为 true,可以从其他域调用 WCF 服务。
CrossDomainScriptAccessEnabled - 获取或设置一个值,该值确定是否启用跨域脚本访问。

如下修改您的 WCF 服务配置文件

<configuration>
  <system.web>
    <compilation debug="true" targetframework="4.0">
    <authentication mode="None">
  </authentication></compilation></system.web>
  <system.webserver>
    <modules runallmanagedmodulesforallrequests="true">
  </modules></system.webserver>
  <system.servicemodel>
    <servicehostingenvironment aspnetcompatibilityenabled="true">
    <standardendpoints>
      <webscriptendpoint>
        <standardendpoint crossdomainscriptaccessenabled="true">
      </standardendpoint></webscriptendpoint>
    </standardendpoints>
  </servicehostingenvironment></system.servicemodel>
</configuration>

如您在上面的配置代码中看到的,我将 crossdomainscriptaccessenabled 设置为 true ,将 aspnetcompatibilityenabled 设置为 true ,以便 WCF 服务像普通 ASMX 服务一样工作并支持所有现有的 ASP.NET 功能。

第二步

服务的 SVC 文件应如下所示

<%@ ServiceHost Language="C#" Debug="true" 
Service="WcfService1.Service1" 
CodeBehind="Service1.svc.cs"
Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"  %> 

不要忘记添加 Factory 属性,因为它在删除时会导致错误。以下是添加 Factory 属性的原因

  1. 服务主机工厂是我们可以在请求到来时动态创建服务主机实例的机制。
  2. 当我们需要实现打开和关闭服务的事件处理程序时,这非常有用。
  3. WCF 为此目的提供了 ServiceFactory 类。

步骤 3

WCF 文件的 CS 文件如下

using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;

namespace WcfService1
{
    [DataContract]
    public class Customer
    {
        [DataMember]
        public string Name;

        [DataMember]
        public string Address;
    }

    [ServiceContract(Namespace = "JsonpAjaxService")]
    [AspNetCompatibilityRequirements(RequirementsMode =   
			AspNetCompatibilityRequirementsMode.Allowed)]
    public class Service1
    {
        [WebGet(ResponseFormat = WebMessageFormat.Json)]
        public Customer GetCustomer()
        {
            return new Customer() { Name = "Pranay", Address = "1 Ahmedabad" };
        }
    }
}

如您在上面的代码中看到的,我创建了 Service 类,这是一个服务契约,用于提供数据,而 Customer 类是 DataContract ,用于响应。
在服务类中,GetCustomer 方法以 Json 格式提供数据。
创建 WCF 服务后,要继续进行,请添加新项目 >> ASP.NET 服务。这样,WCF 服务和网站就可以在两个不同的域上运行,就像它们都托管在不同的域上一样。
有两种方法可以调用跨域 WCF 服务。

解决方案 1:使用 JQuery 调用 WCF 服务

Jquery 已经支持处理 jsonp。Jquery 库提供的 ajax 和 getJson 函数允许调用发送 jsonp 数据作为响应的 WCF 服务。

CallService - 用于调用 WCF 服务的通用函数,由其他 JavaScript 函数调用以获取和显示数据。

var Type;
        var Url;
        var Data;
        var ContentType;
        var DataType;
        var ProcessData;
        var method;
        //Generic function to call WCF  Service
        function CallService() {
            $.ajax({
                type: Type, //GET or POST or PUT or DELETE verb
                url: Url, // Location of the service
                data: Data, //Data sent to server
                contentType: ContentType, // content type sent to server
                dataType: DataType, //Expected data format from server
                processdata: ProcessData, //True or False
                success: function (msg) {//On Successful service call
                    ServiceSucceeded(msg);
                },
                error: ServiceFailed// When Service call fails
            });
        }

ServiceFailed - 在服务调用失败时调用。

function ServiceFailed(xhr) {
            alert(xhr.responseText);
            if (xhr.responseText) {
                var err = xhr.responseText;
                if (err)
                    error(err);
                else
                    error({ Message: "Unknown server error." })
            }
            return;
        }

ServiceSucceeded - 在服务成功返回响应时调用。如您在函数中看到的,我正在检查 DataType is jsonp,这只是为了演示服务正在返回 jsonp 数据。

function ServiceSucceeded(result) {
            if (DataType == "jsonp") {
                
                    resultObject = result.GetEmployeeResult;
                    var string = result.Name + " \n " + result.Address ;
                    alert(string); 
            }
        }

GetEmployee - 是一个被调用的函数,用于请求托管在其他域上的 WCF 服务的数据。如您在代码中看到的,DataType 值被设置为 jsonp

function GetEmployee() {
            var uesrid = "1";
            Type = "GET";
            Url = "https://:52136/Service1.svc/GetCustomer"; 
            DataType = "jsonp"; ProcessData = false;
            method = "GetCustomer";
            CallService();
        }

        $(document).ready(
         function () {
            
             GetEmployee();
         }
);

解决方案 2:通过 JavaScript 调用 WCF 服务

要使用 JavaScript 调用服务,请使用 ScriptManager

 <asp:scriptmanager id="ScriptManager1" runat="server">
        <services>
            <asp:servicereference path="https://:52136/Service1.svc">        
 </services>  

在上面的代码中,我将 servicereference 设置为托管在其他域上的 WCF 服务。

makeCall - 被调用的函数,用于请求托管在另一个域上的 WCF 服务的数据。

function makeCall() {
                      var proxy = new JsonpAjaxService.Service1();
                     proxy.set_enableJsonp(true);
                     proxy.GetCustomer(onSuccess, onFail, null);
                 }

onSuccess - 在收到服务调用结果并显示数据时调用。

function onSuccess(result) {
                     alert( result.Name + " " +result.Address);
                 }

onFail - 在服务调用失败时调用。

function onFail(){
                     alert("Error");
                 } 

摘要

因此,在 WCF 团队添加了特殊属性后,调用跨域 WCF 服务变得非常容易。

参考文献

© . All rights reserved.