前不久出去面试,有家公司让上机写一个增加用户的的程序,当时没写,回来后简单的写了下,算是记录下吧。
实现功能:列表显示和增加。
步骤一:构建整个解决方案
•Contracts:一个类库项目,定义服务契约(Service Contract),引用System.ServiceMode程序集(WCF框架的绝大部分实现和API定义在该程序集中);
•Services:一个类库项目,提供对WCF服务的实现。定义在该项目中的所有WCF服务实现了定义在Contracts中相应的服务契约,所以Services具有对Contracts项目的引用;
•Hosting:一个控制台(Console)应用,实现对定义在Services项目中的服务的寄宿,该项目须要同时引用Contracts和Services两个项目和System.ServiceMode程序集
•ASP.NET MVC3 Web Application:前端界面显示,该项目需要同时引用Contracts项目和System.ServiceMode程序集
对于WCF这一部分的代码,是参考博客园里面的一篇文章,http://www.cnblogs.com/artech/archive/2007/02/26/656901.html(我的WCF之旅(1):创建一个简单的WCF程序)
步骤二:创建服务契约
一般地,我们通过接口的形式定义服务契约。通过下面的代码,将一个接口ICalculator定义成服务契约。WCF广泛采用基于自定义特性(Custom Attribtue)的声明式编程模式,我们通过在接口上应用System.ServiceModel.ServiceContractAttribute特性将一个接口定义成服务契约。通过应用ServiceContractAttribute特性将接口定义成服务契约之后,接口的方法成员并不能自动成为服务的操作。在此方面,WCF采用的是显式选择(Explicit Opt-in)的策略:我们须要在相应的操作方法上面显式地应用OperationContractAttribute特性。
using System.ServiceModel; namespace WcfServices.Contracts { [ServiceContract(Name="UserService",Namespace="http://www.teresa.com/")] public interface IUser { [OperationContract] DataSet GetUsers(); [OperationContract] void AddUser(string name,string stuNo); } }
步骤三:创建服务
当服务契约成功创建时,我们需要通过实现服务契约来创建具体的WCF服务。WCF服务CalculatorService定义在Services项目中,实现了服务契约接口ICalculator,实现了所有的服务操作。CalculatorService定义如下:
using WcfServices.Contracts; namespace WcfServices.Services { public class UserService : IUser { public DataSet GetUsers() { DataSet dst = new DataSet(); string strConn = "server=local;database=WcfTesting;Integrated Security=SSPI"; SqlConnection conn = new SqlConnection(strConn); conn.Open(); string strQueryString = "select * from [User] order by Id desc "; SqlDataAdapter ada=new SqlDataAdapter(strQueryString,conn); ada.Fill(dst); conn.Close(); return dst; } public void AddUser(string name, string stuNo) { string strConn = "server=local;database=WcfTesting;Integrated Security=SSPI"; SqlConnection conn = new SqlConnection(strConn); conn.Open(); string strCommand = string.Format("INSERT INTO [User] values('{0}','{1}')", name, stuNo); SqlCommand com = new SqlCommand(strCommand,conn); com.ExecuteNonQuery(); conn.Close(); } } }
补充说明:User表只建立了三个字段,Id(自增),name,stuNo.
步骤四:通过自我寄宿的方式寄宿服务
WCF服务需要依存一个运行着的进程(宿主),服务寄宿就是为服务指定一个宿主的过程。WCF是一个基于消息的通信框架,采用基于终结点(Endpoint)的通信手段。终结点由地址(Address)、绑定(Binding)和契约(Contract)三要素组成,由于三要素应为首字母分别为ABC,所以就有了易于记忆的公式:Endpoint = ABC。一个终结包含了实现通信所必需的所有信息,我们可以这样认识终结点的ABC: •地址(Address):地址决定了服务的位置,解决了服务寻址的问题 •绑定(Binding):绑定实现了通信的所有细节,包括网络传输、消息编码,以及其他为实现某种功能(比如安全、可靠传输、事务等)对消息进行的相应处理。WCF中具有一系列的系统定义绑定,比如BasicHttpBinding、WsHttpBinding、NetTcpBinding等 •契约(Contract):契约是对服务操作的抽象,也是对消息交换模式以及消息结构的定义
服务寄宿的目的就是开启一个进程,为WCF服务提供一个运行的环境。通过为服务添加一个或多个终结点,使之暴露给潜给的服务消费者。服务消费者最终通过相匹配的终结点对该服务进行调用。我们可以完全通过代码的方式完成所有的服务寄宿工作,下面的代码体现了通过一个控制台应用对CalculatorService的寄宿:
using WcfServices.Contracts; using WcfServices.Services; using System.ServiceModel; using System.ServiceModel.Description; namespace Hosting { class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(UserService))) { host.AddServiceEndpoint(typeof(IUser), new WSHttpBinding(), "http://127.0.0.1:9999/userservice"); if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null) { ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); behavior.HttpGetEnabled = true; behavior.HttpGetUrl = new Uri("http://127.0.0.1:9999/userservice/metadata"); host.Description.Behaviors.Add(behavior); } host.Opened += delegate { Console.WriteLine("CalculatorService started,press any key can stop the service!"); }; host.Open(); Console.Read(); } } } }
WCF服务寄宿通过一个特殊的对象完成:ServiceHost。在上面的例子中,基于WCF服务的类型(typeof(UserService))创建了ServieHost对象,并添加了一个终结点。具体的地址为http://127.0.0.1:9999/UserService,采用了WSHttpBinding,并指定了服务契约的类型IUser。
松耦合是SOA的一个基本的特征,WCF应用中客户端和服务端的松耦合体现在客户端只须要了解WCF服务基本的描述,而无须知道具体的实现细节,就可以实现正常的服务调用。WCF服务的描述通过元数据(Metadata)的形式发布出来。WCF中元数据的发布通过一个特殊的服务行为ServiceMetadataBehavior实现。在上面提供的服务寄宿代码中,我们为创建的ServiceHost添加了ServiceMetadataBehavior,并采用了基于HTTP-GET的元数据获取方式,元数据的发布地址通过ServiceMetadataBehavior的HttpGetUrl指定。在调用ServiceHost的Open方法对服务成功寄宿后,我们可以通过该地址获取服务相关的元数据。在IE地址栏上键入http://127.0.0.1:9999/UserService/metadata,你将会得到以WSDL形式体现的服务元数据。
步骤五:创建MVC web项目实现前端界面显示。
1.新建一个用户control,里面有显示和增加用户的两个Action。
using WcfServices.Contracts; namespace MvcWcf.Controllers { public class UserController : Controller { // // GET: /User/ public ActionResult Index() { return View(); } public ActionResult Users() { using (ChannelFactory<IUser> channelFactory = new ChannelFactory<IUser>(new WSHttpBinding(), "http://127.0.0.1:9999/userservice")) { IUser proxy = channelFactory.CreateChannel(); using (proxy as IDisposable) { ViewBag.Users= proxy.GetUsers().Tables[0]; } } return View(); } [HttpPost] public string AddUser(string name, string num) { try { using (ChannelFactory<IUser> channelFactory = new ChannelFactory<IUser>(new WSHttpBinding(), "http://127.0.0.1:9999/userservice")) { IUser proxy = channelFactory.CreateChannel(); using (proxy as IDisposable) { proxy.AddUser(name, num); return "1"; } } } catch (Exception e) { return e.ToString(); } } } }
2.创建显示用户列表的View。
在方法Users上面右击,选择命令Add View,将进入到Users.cshtml,代码如下:
@{ ViewBag.Title = "Users"; var usersTable = ViewBag.Users; } <script type="text/javascript" src="../../Scripts/jquery-1.5.1.js"></script> <script type="text/javascript"> function AddUser() { $("#tblUser tr").first().after("<tr><td><input type=text /></td><td><input type=text /></td></tr>"); $("#btnSave").attr("style", "display:"); $("#btnCancle").attr("style", "display"); $("#btnAdd").attr("style", "display:none"); } function CancleAdd() { $("#tblUser tr").first().next().remove(); $("#btnSave").attr("style", "display:none"); $("#btnCancle").attr("style", "display:none"); $("#btnAdd").attr("style", "display:"); } function SaveUser() { var name = $("#tblUser tr td :input").first().val(); var num = $("#tblUser tr td :input").last().val(); var KeyNameJason = "{'name':'" + name + "','num':'" + num + "'}"; $.ajax( { type: 'POST', contentType: 'application/json', url: '/User/AddUser', async: false, data: KeyNameJason, dataType: "text", success: function (data) { $("#tblUser tr").first().next().remove(); $("#tblUser tr").first().after("<tr><td>" + name + "</td><td>" + num + "</td></tr>"); $("#btnSave").attr("style", "display:none"); $("#btnCancle").attr("style", "display:none"); $("#btnAdd").attr("style", "display:"); alert("Add user successfully!"); }, error: function (data) { alert(data); } }); } </script> <h2> Users</h2> <div> <div> <input type="button" id="btnAdd" style=" 80px" value="Add" onclick="AddUser();" /> <input type="button" id="btnSave" style="80px; display:none" value="Save" onclick="SaveUser()" /> <input type="button" id="btnCancle" style="80px; display:none" value="Cancle" onclick="CancleAdd()" /> </div> <div> <table border="1" id="tblUser"> <tbody> <tr> <th style=" 120px"> Name </th> <th style=" 120px"> Num </th> </tr> @{ foreach (var row in usersTable.Rows) { <tr> <td>@row[1] </td> <td>@row[2] </td> </tr> } } </tbody> </table> </div> </div>
将该MVC项目设置成启动项目,按F5运行,在地址栏输入如下:http://localhost:[端口号]/User/Users.
就可以看到列表页面和增加之类的按钮了。