WCFRest应用简介

        上周末把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" οnclick="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" οnclick="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了。

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

        源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值