1.采用模板实现WCFRest
一张图说明步骤
如图所示,建立项目,直接运行,在运行的路径后加Service1你就可以得到如下结果:
这就是WCFRest的最简单的例子,我的例子的服务代码如下:
[ServiceContract] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] // NOTE: If the service is renamed,remember to update the global.asax.cs file public class LoginService { // TODO: Implement the collection resource that will contain the SampleItem instances [WebGet(UriTemplate = "All",ResponseFormat = WebMessageFormat.Json)] public List<BaseInfo> All() { List<BaseInfo> list = Factory.GetFactoryInstance(DataProviderEnum.StaticData).All(); return list; } [WebGet(UriTemplate = "Login/{GID}/{PWD}",ResponseFormat = WebMessageFormat.Json)] public BaseInfo Login(string GID,string PWD) { // TODO: Replace the current implementation to return a collection of SampleItem instances return Factory.GetFactoryInstance(DataProviderEnum.StaticData).Login(GID,PWD); } [WebInvoke(UriTemplate = "RegistLogin",Method = "POST",ResponseFormat = WebMessageFormat.Json)] public BaseInfo RegistLogin(BaseInfo baseInfo) { // TODO: Add the new instance of SampleItem to the collection return Factory.GetFactoryInstance(DataProviderEnum.StaticData).RegistLogin(baseInfo); } }服务上面标签暂不考虑,主要关注方法上特性标签。WebGet指明方法采用Get方式,WebInvoke指示服务操作在逻辑上就是调用操作,此时需额外指定Method属性。UriTemplate服务操作的统一资源标识符 (URI) 模板,例如"Login/{Arg1}/{Arg2}",在实际运行时大括号中将以实际值填充URL;ResponseFormat返回的数据格式,有XML和Json两种,默认是XML,例子中均采用Json。
页面调用WCFRest也很简单,可通过jQuery+Ajax实现调用,示例代码如下:
<html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title></title> <script src="jquery-1.4.1.js" type="text/javascript"></script> <script type="text/javascript"> function ShowAllUserInfo() { $.ajax({ type: "GET",url: "LoginService/All",contentType: "application/json;charset=utf-8",dataType: "json",cache: false,success: function (data) { $("#tabAllUser tr:gt(0)").remove(); $.each(data,function (i) { $("#tabAllUser").append("<tr><td>" + data[i].GID + "</td><td>" + data[i].Name + "</td><td>" + data[i].City + "</td></tr>") }) } }); } </script> </head> <body> <input id="btnGetAllInfo" type="button" onclick="ShowAllUserInfo();" value="获得所有信息" /> <table id="tabAllUser"> <tr> <th> GID </th> <th> Name </th> <th> City </th> </tr> </table> </body> </html>运行效果为:
2.采用一般WCF服务的方式实现WCFRest以及客户端的调用
2.1采用一般WCF服务的方式实现WCFRest
跟一般WCF的结构一样,四个部分:契约、服务、宿主、配置文件2.11契约:
[ServiceContract] public interface ILoginService { [OperationContract(Name = "All")] [WebInvoke(Method = "GET",RequestFormat = WebMessageFormat.Json,ResponseFormat = WebMessageFormat.Json,BodyStyle = WebMessageBodyStyle.Bare,UriTemplate = "All")] List<BaseInfo> All(); [OperationContract(Name = "Login")] [WebInvoke(Method = "GET",UriTemplate = "Login/{GID}/{PWD}")] BaseInfo Login(string GID,string PWD); [OperationContract(Name = "RegistLogin")] [WebInvoke(Method = "POST",UriTemplate = "RegistLogin")] BaseInfo RegistLogin(BaseInfo baseInfo); [OperationContract(Name = "Regist")] [WebInvoke(Method = "POST",UriTemplate = "Regist")] void Regist(BaseInfo baseInfo); }
2.12服务:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class LoginService : ILoginService { public List<BaseInfo> All() { List<BaseInfo> list = Factory.GetFactoryInstance(DataProviderEnum.XML).All(); return list; } public BaseInfo Login(string GID,string PWD) { return Factory.GetFactoryInstance(DataProviderEnum.XML).Login(GID,PWD); } public BaseInfo RegistLogin(BaseInfo baseInfo) { return Factory.GetFactoryInstance(DataProviderEnum.XML).RegistLogin(baseInfo); } public void Regist(BaseInfo baseInfo) { Factory.GetFactoryInstance(DataProviderEnum.XML).RegistLogin(baseInfo); } }
2.13宿主:
using (WebServiceHost host = new WebServiceHost(typeof(LoginService))) { Console.WriteLine("服务正在开启..."); host.Open(); Console.WriteLine("服务已经开启..."); Console.ReadLine(); }
2.14配置文件:
<?xml version="1.0"?> <configuration> <system.serviceModel> <standardEndpoints> <webHttpEndpoint> <!--支持跨域,可省略(省略之后无法在浏览器中查看)--> <standardEndpoint crossDomainScriptAccessEnabled="true"/> </webHttpEndpoint> </standardEndpoints> <bindings> <webHttpBinding> <!--支持跨域,必不可少--> <binding crossDomainScriptAccessEnabled="true" /> </webHttpBinding> </bindings> <services> <service name="RestService.LoginService" behaviorConfiguration="behaviorLoginService"> <endpoint address="http://127.0.0.1:3741/LoginService" binding="webHttpBinding" contract="RestContract.ILoginService"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="behaviorLoginService"> <serviceMetadata httpGetEnabled="True"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>注意:配置文件中两个地方需要设置crossDomainScriptAccessEnabled属性为true;在浏览器中输入http://127.0.0.1:3741/LoginService/All即提醒新建下载任务,里面就是获取的服务端的数据,可打开查看。
2.2在Asp.Net中通过JsonP访问
页面代码如下( 注意跟上面对比,dataType为JsonP):<html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title></title> <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script> <script type="text/javascript"> function ShowAllUserInfo() { $.ajax({ type: "GET",url: "http://127.0.0.1:3741/LoginService/All",dataType: "jsonp",function (i) { $("#tabAllUser").append("<tr><td>" + data[i].GID + "</td><td>" + data[i].Name + "</td><td>" + data[i].City + "</td></tr>") }) } }); } </script> </head> <body> <input id="btnGetAllInfo" type="button" onclick="ShowAllUserInfo();" value="获得所有信息" /> <table id="tabAllUser"> <tr> <th> GID </th> <th> Name </th> <th> City </th> </tr> </table> </body> </html>先运行WCFRest服务宿主,再运行网站结果如下:
这边跟采用模板实现WCFRest的区别,模板实现的Rest无法实现跨域,这边可以跨域。
2.3一般程序中访问Rest(ConSole、Winform、WPF、服务端后台等)
主要介绍Post和Get,都是通过WebClient实现。Get代码如下:
private static string GetData(string url) { string json = string.Empty; WebClient webClient = new WebClient(); Uri uri = new Uri(url,UriKind.Absolute); if (bool.Equals(false,webClient.IsBusy)) { webClient.Encoding = System.Text.Encoding.UTF8; json = webClient.DownloadString(uri); } return json; }Post代码如下:
private static string PostData(string url,string jsonData) { WebClient webClient = new WebClient(); byte[] byteData = Encoding.UTF8.GetBytes(jsonData.ToString()); webClient.Headers.Add("Content-Type","application/json"); webClient.Headers.Add("ContentLength",byteData.Length.ToString()); byte[] resultData = webClient.UploadData(url,"POST",byteData); string json = Encoding.UTF8.GetString(resultData); return json; }注意的是,这边获得的结果均为Json字符串,需要将其转换为需要的对象或者值,我这边用的第三方的Json.net实现的(个人不喜欢微软自带的序列化类,时间老有问题)。
控制台完整代码:
class Program { const string postRegistLoginUrl = @"http://127.0.0.1:3741/LoginService/RegistLogin"; const string getAllUrl = @"http://127.0.0.1:3741/LoginService/All"; static void Main(string[] args) { Console.WriteLine("Begin"); //Post操作,RegistLogin BaseInfo newUser = new BaseInfo() { GID = "test0914",PWD = "pwd0914",Name = "name0914"}; string jsonPostData = JsonConvert.SerializeObject(newUser); string postResult=PostData(postRegistLoginUrl,jsonPostData); Console.WriteLine("postRegistLogin Result:" + postResult); //Get操作,All string getResult = GetData(getAllUrl); Console.WriteLine("getAll Result:" + getResult); //返回值处理 var allUserList = JsonConvert.DeserializeObject<List<BaseInfo>>(getResult); foreach (var user in allUserList) { string userInfo = string.Format("GID:{0};Name:{1};City:{2}",user.GID,user.Name,user.City); Console.WriteLine(userInfo); } Console.WriteLine("End"); Console.ReadLine(); } private static string GetData(string url) { string json = string.Empty; WebClient webClient = new WebClient(); Uri uri = new Uri(url,UriKind.Absolute); if (bool.Equals(false,webClient.IsBusy)) { webClient.Encoding = System.Text.Encoding.UTF8; json = webClient.DownloadString(uri); } return json; } private static string PostData(string url,string jsonData) { WebClient webClient = new WebClient(); byte[] byteData = Encoding.UTF8.GetBytes(jsonData.ToString()); webClient.Headers.Add("Content-Type","application/json"); webClient.Headers.Add("ContentLength",byteData.Length.ToString()); byte[] resultData = webClient.UploadData(url,byteData); string json = Encoding.UTF8.GetString(resultData); return json; } }项目整体结构如下:
2.4Android访问WCFRest(参照上篇博客)
3.小结
个人觉得在内部网站项目中可以采用模板实现WCFRest,优点是安全和解耦,缺点是无法跨域访问、发布只能通过IIS发布。对于多平台的接口(Android、桌面和服务端,不包含复杂的Web应用)可以考虑采用WCFRest。如果也包括Web应用可以考虑采用其他绑定的WCF,一般也不考虑Webservice了。 至此全部完成,只是个人的一些实践,对自己是一个记录,同时希望也能对别人有些帮助,如果有什么错误,还望不吝指出,共同进步,转载请保留原文地址。