您的位置:首页 > 其它

WCFRest应用简介

2014-09-16 22:09 405 查看
上周末把WCFRest稍微整理了下,不料到最后一步发现Post跨域提交不成功,调查了两晚还是没有什么解决方案,暂且当作其的一个缺陷吧(本质与WCFRest无关,是JsonP不支持跨域Post,或者说JsonP跨域的本质是还是Get)。示例主要分为两个方面:1.采用模板实现WCFRest;2.采用一般WCF服务的方式实现WCFRest以及客户端的调用。

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",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "Login/{GID}/{PWD}")]
BaseInfo Login(string GID, string PWD);

[OperationContract(Name = "RegistLogin")]
[WebInvoke(Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "RegistLogin")]
BaseInfo RegistLogin(BaseInfo baseInfo);

[OperationContract(Name = "Regist")]
[WebInvoke(Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
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",
contentType: "application/json;charset=utf-8",
dataType: "jsonp",
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>
先运行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, "POST", byteData); string json = Encoding.UTF8.GetString(resultData); return json; }
}
项目整体结构如下:



2.4Android访问WCFRest(参照上篇博客

3.小结

个人觉得在内部网站项目中可以采用模板实现WCFRest,优点是安全和解耦,缺点是无法跨域访问、发布只能通过IIS发布。对于多平台的接口(Android、桌面和服务端,不包含复杂的Web应用)可以考虑采用WCFRest。如果也包括Web应用可以考虑采用其他绑定的WCF,一般也不考虑Webservice了。

至此全部完成,只是个人的一些实践,对自己是一个记录,同时希望也能对别人有些帮助,如果有什么错误,还望不吝指出,共同进步,转载请保留原文地址

源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: