[源码下载]
化零为整WCF(18) - Web编程模型(WCF创建REST, AJAX调用WCF)
作者:webabcd
介绍
WCF(Windows Communication Foundation) - Web编程模型:使用WCF创建REST服务,使用asp.net ajax调用WCF服务
·System.ServiceModel.Activation.WebServiceHostFactory - 用于承载使用 WCF Web 编程模型的服务
·System.ServiceModel.Activation.WebScriptServiceHostFactory - 能够向服务中自动添加 ASP.NET AJAX 终结点而无需进行配置
示例(使用WCF创建REST服务)
1、服务
User.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace WCF.ServiceLib.Web
{
/// <summary>
/// User实体类
/// </summary>
[DataContract]
public class User
{
/// <summary>
/// 用户名
/// </summary>
[DataMember(Order = 0)]
public string Name { get; set; }
/// <summary>
/// 生日
/// </summary>
[DataMember(Order = 1)]
public DateTime DayOfbirth { get; set; }
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace WCF.ServiceLib.Web
{
/// <summary>
/// User实体类
/// </summary>
[DataContract]
public class User
{
/// <summary>
/// 用户名
/// </summary>
[DataMember(Order = 0)]
public string Name { get; set; }
/// <summary>
/// 生日
/// </summary>
[DataMember(Order = 1)]
public DateTime DayOfbirth { get; set; }
}
}
IREST.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace WCF.ServiceLib.Web
{
/// <summary>
/// 演示REST(Representational State Transfer)的接口
/// </summary>
/// <remarks>
/// HTTP方法中:
/// PUT相当于Update
/// GET相当于Read
/// POST相当于Create
/// DELETE相当于Delete
/// </remarks>
[ServiceContract]
public interface IREST
{
/// <summary>
/// 创建用户
/// </summary>
/// <param name="name">用户名</param>
/// <param name="dayOfbirth">生日</param>
/// <remarks>
/// WebInvoke - 指示服务操作在逻辑上就是调用操作,而且可由 Web 编程模型调用
/// UriTemplate - 用于服务操作的统一资源标识符 (URI) 模板。URI模板可以将一个 URI 或一组 URI 映射到服务操作。有关 URI 模板的更多信息,请参见 UriTemplate 和 UriTemplateTable
/// Method - 与操作关联的协议方法,默认为 POST
/// ResponseFormat - 指定从服务操作发出的响应的格式。Xml 或 Json
/// </remarks>
[OperationContract]
[WebInvoke(
UriTemplate = "User/{name}/{dayOfbirth}",
Method = "PUT",
ResponseFormat = WebMessageFormat.Json)]
User CreateUser(string name, string dayOfbirth);
/// <summary>
/// 获取用户信息
/// </summary>
/// <param name="name">用户名</param>
/// <remarks>
/// WebGet - 指示服务操作在逻辑上就是检索操作,而且可由 Web 编程模型调用
/// </remarks>
[OperationContract]
[WebGet(
UriTemplate = "User/{name}",
ResponseFormat = WebMessageFormat.Json)]
User GetUser(string name);
/// <summary>
/// 更新用户信息
/// </summary>
/// <param name="name">用户名</param>
/// <param name="dayOfbirth">生日</param>
/// <returns></returns>
[OperationContract]
[WebInvoke(UriTemplate = "User/{name}/{dayOfbirth}",
Method = "POST",
ResponseFormat = WebMessageFormat.Json)]
bool UpdateUser(string name, string dayOfbirth);
/// <summary>
/// 删除用户信息
/// </summary>
/// <param name="name">用户名</param>
/// <returns></returns>
[OperationContract]
[WebInvoke(
UriTemplate = "User/{name}",
Method = "DELETE",
ResponseFormat = WebMessageFormat.Json)]
bool DeleteUser(string name);
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace WCF.ServiceLib.Web
{
/// <summary>
/// 演示REST(Representational State Transfer)的接口
/// </summary>
/// <remarks>
/// HTTP方法中:
/// PUT相当于Update
/// GET相当于Read
/// POST相当于Create
/// DELETE相当于Delete
/// </remarks>
[ServiceContract]
public interface IREST
{
/// <summary>
/// 创建用户
/// </summary>
/// <param name="name">用户名</param>
/// <param name="dayOfbirth">生日</param>
/// <remarks>
/// WebInvoke - 指示服务操作在逻辑上就是调用操作,而且可由 Web 编程模型调用
/// UriTemplate - 用于服务操作的统一资源标识符 (URI) 模板。URI模板可以将一个 URI 或一组 URI 映射到服务操作。有关 URI 模板的更多信息,请参见 UriTemplate 和 UriTemplateTable
/// Method - 与操作关联的协议方法,默认为 POST
/// ResponseFormat - 指定从服务操作发出的响应的格式。Xml 或 Json
/// </remarks>
[OperationContract]
[WebInvoke(
UriTemplate = "User/{name}/{dayOfbirth}",
Method = "PUT",
ResponseFormat = WebMessageFormat.Json)]
User CreateUser(string name, string dayOfbirth);
/// <summary>
/// 获取用户信息
/// </summary>
/// <param name="name">用户名</param>
/// <remarks>
/// WebGet - 指示服务操作在逻辑上就是检索操作,而且可由 Web 编程模型调用
/// </remarks>
[OperationContract]
[WebGet(
UriTemplate = "User/{name}",
ResponseFormat = WebMessageFormat.Json)]
User GetUser(string name);
/// <summary>
/// 更新用户信息
/// </summary>
/// <param name="name">用户名</param>
/// <param name="dayOfbirth">生日</param>
/// <returns></returns>
[OperationContract]
[WebInvoke(UriTemplate = "User/{name}/{dayOfbirth}",
Method = "POST",
ResponseFormat = WebMessageFormat.Json)]
bool UpdateUser(string name, string dayOfbirth);
/// <summary>
/// 删除用户信息
/// </summary>
/// <param name="name">用户名</param>
/// <returns></returns>
[OperationContract]
[WebInvoke(
UriTemplate = "User/{name}",
Method = "DELETE",
ResponseFormat = WebMessageFormat.Json)]
bool DeleteUser(string name);
}
}
REST.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace WCF.ServiceLib.Web
{
/// <summary>
/// 演示REST(Representational State Transfer)的类
/// </summary>
public class REST : IREST
{
public User CreateUser(string name, string dayOfbirth)
{
return new User { Name = name, DayOfbirth = DateTime.Parse(dayOfbirth) };
}
public User GetUser(string name)
{
return new User { Name = name, DayOfbirth = new DateTime(1980, 2, 14) };
}
public bool UpdateUser(string name, string dayOfbirth)
{
return true;
}
public bool DeleteUser(string name)
{
return true;
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace WCF.ServiceLib.Web
{
/// <summary>
/// 演示REST(Representational State Transfer)的类
/// </summary>
public class REST : IREST
{
public User CreateUser(string name, string dayOfbirth)
{
return new User { Name = name, DayOfbirth = DateTime.Parse(dayOfbirth) };
}
public User GetUser(string name)
{
return new User { Name = name, DayOfbirth = new DateTime(1980, 2, 14) };
}
public bool UpdateUser(string name, string dayOfbirth)
{
return true;
}
public bool DeleteUser(string name)
{
return true;
}
}
}
2、宿主
REST.svc
<%@ ServiceHost Language="C#" Debug="true" Service="WCF.ServiceLib.Web.REST" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
注:System.ServiceModel.Activation.WebServiceHostFactory - 用于承载使用 WCF Web 编程模型的服务Web.config
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WebBehavior">
<!--httpGetEnabled - 指示是否发布服务元数据以便使用 HTTP/GET 请求进行检索,如果发布 WSDL,则为 true,否则为 false,默认值为 false-->
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="RESTBehavior">
<!--webHttp - 启用 WCF 服务的 Web 编程模型-->
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<!--name - 提供服务的类名-->
<!--behaviorConfiguration - 指定相关的服务行为配置-->
<service name="WCF.ServiceLib.Web.REST" behaviorConfiguration="WebBehavior">
<!--address - 服务地址-->
<!--binding - 通信方式-->
<!--contract - 服务契约-->
<!--behaviorConfiguration - 指定相关的端点行为配置-->
<endpoint address="" binding="webHttpBinding" contract="WCF.ServiceLib.Web.IREST" behaviorConfiguration="RESTBehavior" />
</service>
</services>
</system.serviceModel>
</configuration>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WebBehavior">
<!--httpGetEnabled - 指示是否发布服务元数据以便使用 HTTP/GET 请求进行检索,如果发布 WSDL,则为 true,否则为 false,默认值为 false-->
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="RESTBehavior">
<!--webHttp - 启用 WCF 服务的 Web 编程模型-->
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<!--name - 提供服务的类名-->
<!--behaviorConfiguration - 指定相关的服务行为配置-->
<service name="WCF.ServiceLib.Web.REST" behaviorConfiguration="WebBehavior">
<!--address - 服务地址-->
<!--binding - 通信方式-->
<!--contract - 服务契约-->
<!--behaviorConfiguration - 指定相关的端点行为配置-->
<endpoint address="" binding="webHttpBinding" contract="WCF.ServiceLib.Web.IREST" behaviorConfiguration="RESTBehavior" />
</service>
</services>
</system.serviceModel>
</configuration>
3、客户端
REST.aspx
<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="REST.aspx.cs"
Inherits="Web_REST" Title="WCF创建REST" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<asp:Label ID="lblMsg" runat="server" />
</asp:Content>
Inherits="Web_REST" Title="WCF创建REST" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<asp:Label ID="lblMsg" runat="server" />
</asp:Content>
REST.aspx.cs
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Net;
public partial class Web_REST : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var client = new WebClient();
var create = client.UploadString("http://localhost:3502/ServiceHost/Web/REST.svc/User/webabcd/1980-2-14", "PUT", string.Empty);
var read = client.DownloadString("http://localhost:3502/ServiceHost/Web/REST.svc/User/webabcd");
var update = client.UploadString("http://localhost:3502/ServiceHost/Web/REST.svc/User/webabcd/1980-2-14", "POST", string.Empty);
var delete = client.UploadString("http://localhost:3502/ServiceHost/Web/REST.svc/User/webabcd", "DELETE", string.Empty);
lblMsg.Text = string.Format("{0}<br />{1}<br />{2}<br />{3}",
create,
read,
update,
delete);
}
}
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Net;
public partial class Web_REST : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var client = new WebClient();
var create = client.UploadString("http://localhost:3502/ServiceHost/Web/REST.svc/User/webabcd/1980-2-14", "PUT", string.Empty);
var read = client.DownloadString("http://localhost:3502/ServiceHost/Web/REST.svc/User/webabcd");
var update = client.UploadString("http://localhost:3502/ServiceHost/Web/REST.svc/User/webabcd/1980-2-14", "POST", string.Empty);
var delete = client.UploadString("http://localhost:3502/ServiceHost/Web/REST.svc/User/webabcd", "DELETE", string.Empty);
lblMsg.Text = string.Format("{0}<br />{1}<br />{2}<br />{3}",
create,
read,
update,
delete);
}
}
运行结果:
{"Name":"webabcd","DayOfbirth":"\/Date(319305600000+0800)\/"}
{"Name":"webabcd","DayOfbirth":"\/Date(319305600000+0800)\/"}
true
true
示例(使用asp.net ajax调用WCF服务)
1、服务
User.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace WCF.ServiceLib.Web
{
/// <summary>
/// User实体类
/// </summary>
[DataContract]
public class User
{
/// <summary>
/// 用户名
/// </summary>
[DataMember(Order = 0)]
public string Name { get; set; }
/// <summary>
/// 生日
/// </summary>
[DataMember(Order = 1)]
public DateTime DayOfbirth { get; set; }
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace WCF.ServiceLib.Web
{
/// <summary>
/// User实体类
/// </summary>
[DataContract]
public class User
{
/// <summary>
/// 用户名
/// </summary>
[DataMember(Order = 0)]
public string Name { get; set; }
/// <summary>
/// 生日
/// </summary>
[DataMember(Order = 1)]
public DateTime DayOfbirth { get; set; }
}
}
IAJAX.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace WCF.ServiceLib.Web
{
/// <summary>
/// 演示AJAX的接口
/// </summary>
[ServiceContract(Namespace = "WCF")]
public interface IAJAX
{
/// <summary>
/// 获取用户
/// </summary>
/// <param name="name">用户名</param>
/// <returns></returns>
[OperationContract]
User GetUser(string name);
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace WCF.ServiceLib.Web
{
/// <summary>
/// 演示AJAX的接口
/// </summary>
[ServiceContract(Namespace = "WCF")]
public interface IAJAX
{
/// <summary>
/// 获取用户
/// </summary>
/// <param name="name">用户名</param>
/// <returns></returns>
[OperationContract]
User GetUser(string name);
}
}
AJAX.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Activation;
namespace WCF.ServiceLib.Web
{
/// <summary>
/// 演示AJAX的类
/// </summary>
/// <remarks>
/// ASP.NET 兼容性模型:
/// 如果在负载平衡或者甚至 Web 园的环境中承载 WCF 服务,并且在该环境中后续的会话请求可以被此环境内的不同宿主或进程处理,则需要对会话状态进行进程外持久存储。最新的 WCF 不支持会话状态的持久存储。相反,WCF 将它的所有会话状态存储在内存中。如果在 IIS 中承载 WCF 服务,最后可以使用回收方案。
/// WCF 依赖于会话状态的 ASP.NET 实现,而不是为会话全部再次建立持久存储。此方式有一个严重的限制:使服务仅限于 HTTP
/// ASP.NET 会话状态不是受 ASP.NET 兼容性模式支持的唯一功能。它还支持诸如 HttpContext、globalization 和模拟等功能,就像用于 ASP.NET Web 服务 (ASMX) 一样
/// </remarks>
/// [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class AJAX : IAJAX
{
public User GetUser(string name)
{
return new User { Name = name, DayOfbirth = new DateTime(1980, 2, 14) };
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Activation;
namespace WCF.ServiceLib.Web
{
/// <summary>
/// 演示AJAX的类
/// </summary>
/// <remarks>
/// ASP.NET 兼容性模型:
/// 如果在负载平衡或者甚至 Web 园的环境中承载 WCF 服务,并且在该环境中后续的会话请求可以被此环境内的不同宿主或进程处理,则需要对会话状态进行进程外持久存储。最新的 WCF 不支持会话状态的持久存储。相反,WCF 将它的所有会话状态存储在内存中。如果在 IIS 中承载 WCF 服务,最后可以使用回收方案。
/// WCF 依赖于会话状态的 ASP.NET 实现,而不是为会话全部再次建立持久存储。此方式有一个严重的限制:使服务仅限于 HTTP
/// ASP.NET 会话状态不是受 ASP.NET 兼容性模式支持的唯一功能。它还支持诸如 HttpContext、globalization 和模拟等功能,就像用于 ASP.NET Web 服务 (ASMX) 一样
/// </remarks>
/// [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class AJAX : IAJAX
{
public User GetUser(string name)
{
return new User { Name = name, DayOfbirth = new DateTime(1980, 2, 14) };
}
}
}
2、宿主
AJAX.svc
<%@ ServiceHost Language="C#" Debug="true" Service="WCF.ServiceLib.Web.AJAX" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" %>
注:System.ServiceModel.Activation.WebScriptServiceHostFactory - 能够向服务中自动添加 ASP.NET AJAX 终结点而无需进行配置Web.config
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WebBehavior">
<!--httpGetEnabled - 指示是否发布服务元数据以便使用 HTTP/GET 请求进行检索,如果发布 WSDL,则为 true,否则为 false,默认值为 false-->
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="AJAXBehavior">
<!--enableWebScript - 启用 WCF 服务的 脚本 编程模型-->
<enableWebScript />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<!--name - 提供服务的类名-->
<!--behaviorConfiguration - 指定相关的服务行为配置-->
<service name="WCF.ServiceLib.Web.AJAX" behaviorConfiguration="WebBehavior">
<!--address - 服务地址-->
<!--binding - 通信方式-->
<!--contract - 服务契约-->
<!--behaviorConfiguration - 指定相关的端点行为配置-->
<endpoint address="" binding="webHttpBinding" contract="WCF.ServiceLib.Web.IAJAX" behaviorConfiguration="AJAXBehavior" />
</service>
</services>
</system.serviceModel>
</configuration>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WebBehavior">
<!--httpGetEnabled - 指示是否发布服务元数据以便使用 HTTP/GET 请求进行检索,如果发布 WSDL,则为 true,否则为 false,默认值为 false-->
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="AJAXBehavior">
<!--enableWebScript - 启用 WCF 服务的 脚本 编程模型-->
<enableWebScript />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<!--name - 提供服务的类名-->
<!--behaviorConfiguration - 指定相关的服务行为配置-->
<service name="WCF.ServiceLib.Web.AJAX" behaviorConfiguration="WebBehavior">
<!--address - 服务地址-->
<!--binding - 通信方式-->
<!--contract - 服务契约-->
<!--behaviorConfiguration - 指定相关的端点行为配置-->
<endpoint address="" binding="webHttpBinding" contract="WCF.ServiceLib.Web.IAJAX" behaviorConfiguration="AJAXBehavior" />
</service>
</services>
</system.serviceModel>
</configuration>
3、客户端
Demo.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Demo.aspx.cs" Inherits="Demo" %>
<!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>AJAX调用WCF</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="Service/AJAX.svc" />
</Services>
</asp:ScriptManager>
<asp:Label ID="lblMsg" runat="server" />
<script type="text/javascript">
function pageLoad()
{
var proxy = new WCF.IAJAX();
proxy.GetUser("webabcd", onSuccess);
}
function onSuccess(result)
{
$get('<%= lblMsg.ClientID %>').innerHTML =
String.format("姓名:{0}<br />生日:{1}", result.Name, result.DayOfbirth.format("yyyy-MM-dd"));
}
</script>
</form>
</body>
</html>
<!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>AJAX调用WCF</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="Service/AJAX.svc" />
</Services>
</asp:ScriptManager>
<asp:Label ID="lblMsg" runat="server" />
<script type="text/javascript">
function pageLoad()
{
var proxy = new WCF.IAJAX();
proxy.GetUser("webabcd", onSuccess);
}
function onSuccess(result)
{
$get('<%= lblMsg.ClientID %>').innerHTML =
String.format("姓名:{0}<br />生日:{1}", result.Name, result.DayOfbirth.format("yyyy-MM-dd"));
}
</script>
</form>
</body>
</html>
运行结果:
姓名:webabcd
生日:1980-02-14
OK
[源码下载]