Javascript 调用自宿主WCF(invoke self hosted wcf from js/ajax)
在ASP.Net中MS已经集成了WCF方式的WebService,这样利用Ajax Enabled WCf就可以轻松的实现JS调用WCf功能。
但是在某些特定环境下(例如WebGame后台服务器程序)我们需要利用JS直接调用非IIS宿主的WCF服务,如果你Google过,就会发现在网上找到的大多数方案都是利用ASP.NET充当一个代理(先利用ASP.NET调用一次,再在ASP.NET网站中封装一下,以便JS调用)。这样做的好处是可以解决跨域访问的问题,并且调用起来也挺简单的。
下面,我们通过实例来说明如何利用JS直接调用非IIS宿主的WCF。JS调用WCF无非要解决两个问题,1.如何获取JS代理类,2.如何解决跨域问题。今天主要解决第1个问题,关于跨域问题会在后面的文章中加以解决(利用JSONP)。
1. 建立一个自宿主WCF(self hosted wcf)
建立一个WCf服务器,其中包括一个函数,如下所示:
namespace WCFTest
{
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetHello(string uid);
}
public class Service1 : IService1
{
#region IService1 Members
public string GetHello(string uid)
{
return "hello " + uid;
}
#endregion
}
}
2. 在一个Windows窗口程序中启动该服务器,代码如下:
private void Form1_Load(object sender, EventArgs e)
{
ServiceHost host = new ServiceHost(typeof (Service1));
host.Open();
}
3. 在App.config中查看该WCF的网址,并运行主程序
4. 在浏览器打开WCF的网站,如下图所示:
大家知道,如果在ASP.NET中添加WCF模板,IDE会自动为我们生成一个svc文件,而JS的代理类正是通过这个SVC文件得到的,但是在刚才生成的WCF中是无法得到SVC文件以及JS的代理类的,这样就无法被JS所调用,如何解决呢?让我们先来看一下在ASP.NET中添加了一个WCF后,Web.Config是如何配置的,如下所示:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="ServiceAspNetAjaxBehavior">
<enableWebScript />
behavior>
endpointBehaviors>
behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service name="Service">
<endpoint address="" behaviorConfiguration="ServiceAspNetAjaxBehavior"
binding="webHttpBinding" contract="Service" />
service>
services>
system.serviceModel>
关键就在于该服务绑定了webHttpBinding,并且在其行为中(ServiceAspNetAjaxBehavior)启用了EnableWebScript。
再看一下刚才那个WCF程序的App.Config文件,如下所示:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
behavior>
serviceBehaviors>
behaviors>
<services>
<service name="WCFTest.Service1">
<endpoint address="" binding="wsHttpBinding" contract="WCFTest.IService1">
<identity>
<dns value="localhost" />
identity>
endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/WCFTest/Service1/" />
baseAddresses>
host>
service>
services>
system.serviceModel>
并不难发现该WCF服务使用的是wsHttpBinding, 参照ASP.NET中的WCf将该WCF的配置文件进行修改,修改后如下所示:
<system.serviceModel>
<behaviors>
<endpointBehaviors >
<behavior name ="MyBehavior">
<enableWebScript/>
behavior>
endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
behavior>
serviceBehaviors>
behaviors>
<services>
<service name="WCFTest.Service1">
<endpoint address="" binding="wsHttpBinding" contract="WCFTest.IService1">
<identity>
<dns value="localhost" />
identity>
endpoint>
address ="http://localhost/WCFTest"
behaviorConfiguration ="MyBehavior"
>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/WCFTest/Service1/" />
baseAddresses>
host>
service>
services>
注意,这里是添加了一个EndPoint,并将其使用的协议设置为WebHttpBinding(如加粗位置所示),当然这里也体现出WCF可以多协议绑定的方便之处。
现在可以尝试启动该WCF服务了,启动之后,输入如下网址:http://localhost/WCFTest/js,浏览器便会提示下载一个JS文件(没有扩展名的),如下图所示:
有了前面的准备,我们就可以在相同的域内(IP相同,端口也要相同)访问非IIS的WCF了。过程如下:
1. 寻立一个ASP.NET网站
2. 在页面中添加一个ScriptManager,基代码如下:
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Path="http://localhost/WCFTest/js" />
Scripts>
asp:ScriptManager>
3. 添加JS代码以及HTML代码来完善功能
页面代码如下所示:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>title>
<script language="javascript" type="text/javascript">
//
function Button1_onclick() {
var userName = $get("Text1").value;
tempuri.org.IService1.GetHello(userName, function (result) {
alert(result );
});
}
// ]]>
script>
head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Path="http://localhost/WCFTest/js" />
Scripts>
asp:ScriptManager>
<input id="Text1" type="text" /><input id="Button1" type="button"
value="button" onclick="return Button1_onclick()" />div>
form>
body>
html>
4. 运行结果,如下所示: