.NET下RestFulService使用(1) WCF实现RestFul服务端

项目需要要和别人对接,对方用的是RestFul接口,Java平台的,我们是.NET平台的,需要编写RestFul调用客户端,为了测试也要相应的服务端,虽然我也会Java语言,但是不熟啊,搞个环境都要一两天。还是用c#模拟一下就好了。

看了点《RESTful Web APIs中文版》电子版的,还在看理论阶段,电子版的只有一半没找到完整版的。

一、RestFul服务端

参考:https://blog.csdn.net/boonya/article/details/46424099

按我理解是用WCF的服务来实现的RestFul,在OperationContract的基础上增加WebGet特性,使之能够路由到相应的函数进行处理。

WCF是微软通信相关技术的集成,RestFul是一种架构风格,和一般的WCF服务的区别就是{id}这种参数的路由了吧。

我是要在前面参考的基础上再扩展一下的。

1.修改Uri或者变量

原来的是

    [ServiceContract(Name = "RestDemoServices")]
    public interface IRestDemoServices
    {
        [OperationContract]
        [WebGet(UriTemplate = "/Client/{id}", BodyStyle=WebMessageBodyStyle.Bare)]
        string GetClientNameById(string id);
    }

 1.1修改变量名id为name,程序可以运行,但是出现异常,结论:方法变量名和Url里面的变量名必须相同。

An unhandled exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.Web.dll

Additional information: 约定“RestDemoServices”中的操作“GetClientNameById”应具有名称为“ID”的参数的 UriTemplate,但该操作并没有此名称的输入参数。

1.2 修改变量名为ID,没问题,结论:大小写无关。

1.3 将id的类型改为int,出现异常,

Additional information: 约定“RestDemoServices”中的操作“GetClientNameById”具有非“字符串”类型的路径变量“id”。UriTemplate 路径段的变量类型必须为“字符串”。

搜索发现,路径变量必须是string类型,参数可以是int类型

        [OperationContract]
        [WebGet(UriTemplate = "/Clients/{id}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
        Client GetClientById(string id);

        [OperationContract]
        [WebGet(UriTemplate = "/Clients/?id={id}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
        Client QueryClientById(int id);
        public Client GetClientById(string id)
        {
            string result = string.Format("[{0}][GetClientById] id is : {1}", DateTime.Now, id);
            Client client = Clients.Find(i => i.Id.ToString() == id);
            if (client == null) return null;
            client.Message = result;
            return client;
        }

         public Client QueryClientById(int id)
        {
            string result = string.Format("[{0}][QueryClientById] id is : {1}", DateTime.Now, id);
            Client client = Clients.Find(i => i.Id == id);
            if (client == null) return null;
            client.Message = result;
            return client;
        }

不过这样的话会出现使用http://localhost:8111/DemoService/Clients/,会跳到QueryClientById,并且id=0的情况。

1.4 不同方法,相同的Uri,出现异常:

    [ServiceContract(Name = "RestDemoServices")]
    public interface IRestDemoServices
    {   
        [OperationContract]
        [WebGet(UriTemplate = "/Client/{id}", BodyStyle=WebMessageBodyStyle.Bare)]
        string GetClientNameById(string id);

        [OperationContract]
        [WebGet(UriTemplate = "/Client/{id}", BodyStyle = WebMessageBodyStyle.Bare)]
        string GetClientById(string id);    
    }
Additional information: 在约定“RestDemoServices”中,有多个方法为“GET”且 UriTemplate 为“/Client/{id}”的操作。每个操作都需要 UriTemplate 和方法的唯一组合才能明确地调度消息。请使用 WebGetAttribute 或 WebInvokeAttribute 改变操作的 UriTemplate 和方法值。

1.5 uri变量不在最后,没问题。

    [ServiceContract(Name = "RestDemoServices")]
    public interface IRestDemoServices
    {   
        [OperationContract]
        [WebGet(UriTemplate = "/Client/{id}/name", BodyStyle=WebMessageBodyStyle.Bare)]
        string GetClientNameById(string id);

        [OperationContract]
        [WebGet(UriTemplate = "/Client/{id}", BodyStyle = WebMessageBodyStyle.Bare)]
        string GetClientById(string id);    
    }

1.6 去掉OperationContract,没问题

    [ServiceContract(Name = "RestDemoServices")]
    public interface IRestDemoServices
    {
        //[OperationContract]
        string Test();

        //[OperationContract]
        [WebGet(UriTemplate = "/Clients", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
        Client[] GetClients();

        //[OperationContract]
        [WebGet(UriTemplate = "/Clients/{id}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        Client GetClientById(string id);

        //[OperationContract]
        [WebGet(UriTemplate = "/Clients/{id}/name", BodyStyle=WebMessageBodyStyle.Bare,ResponseFormat = WebMessageFormat.Json)]
        Client GetClientNameById(string id);
    }

这样考虑的话,有OperationContract是不是即是RestFul风格的也是RPC风格的,后面客户端再测试一下。

1.7 参数

        [WebGet(UriTemplate = "/Clients?q1={q1}&q2={q2}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
        Client[] GetClients(string q1,int q2);

可以只设置某一个,也可以都不设置;没有设置参数的情况下,string类型为null,int类型为0。

1.8 参数和路径变量 下面的设置可以生成,运行会出异常

        //[OperationContract]
        [WebGet(UriTemplate = "/Clients?q1={q1}&q2={q2}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
        Client[] GetClients(int q1,int q2);

        [WebGet(UriTemplate = "/Clients/{q1}/{q2}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
        Client[] GetClients(string q1, string q2);
Additional information: 同一个协定中不能存在两个名称相同的操作,类型为 RestFulServiceTest.IRestDemoServices 的方法 GetClients 和 GetClients 违反了此规则。可以通过更改方法名称或使用 OperationContractAttribute 的 Name 属性更改其中一个操作的名称。

改成下面就可以了:

        [WebGet(UriTemplate = "/Clients?q1={q1}&q2={q2}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
        Client[] QueryClients(int q1,int q2);

        [WebGet(UriTemplate = "/Clients/{q1}/{q2}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
        Client[] GetClients(string q1, string q2);

http://localhost:8111/DemoService/Clients/1 进入GetClientById

http://localhost:8111/DemoService/Clients/1/2 进入 GetClients

1.9 复杂路径变量

        [WebGet(UriTemplate = "/Clients/{q1},{q2},{q3}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
        Client[] QueryClientsEx(string q1, string q2, string q3);

这样也是可以的,但是这里的string改成int就不行了,这些q1,q2,q3是路径变量。

类似的

        [WebGet(UriTemplate = "/Clients/{q1},{q2},{q3}/{id}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
        Client GetClientByIdEx(string q1, string q2, string q3,string id);
        [WebGet(UriTemplate = "/Clients/{a}_{b}/{id}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
        Client GetClientByIdEx2(string a, string b, string id);

也可以

2.返回json格式

WebGet中设置ResponseFormat = WebMessageFormat.Json,默认的其实是Xml格式,返回结果为类时就能看到结构了

3.post,put,delete

        [WebInvoke(UriTemplate = "/Clients",Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        Client CreateClient(Client client);

        [WebInvoke(UriTemplate = "/Clients", Method = "PUT", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        Client UpdateClient(Client client);

        [WebInvoke(UriTemplate = "/Clients/{id}", Method = "DELETE", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        Client DeleteClient(string id);
       public Client CreateClient(Client client)
        {
            IdFlag++;
            client.Id = IdFlag;
            client.Message = "CREATE";
            Clients.Add(client);
            return client;
        }

        public Client UpdateClient(Client clientNew)
        {
            Client client = Clients.Find(i => i.Id == clientNew.Id);
            client.Name = clientNew.Name;
            client.Message = "UPDATE";
            return client;
        }

        public Client DeleteClient(string id)
        {
            Client client = Clients.Find(i => i.Id+"" == id+"");
            if (client == null) return null;
            Clients.Remove(client);
            client.Message = "DELETE";
            return client;
        }

注意,在写delete时UriTemplate中少了{id}服务端也是能正常运行的,但是客户端出现403错误。

而且路径参数中的路径变量和方法中的变量不需要一一对应,可能是WebInvoke的检查没有WebGet严格吧,自己要注意。

像{id}少了的情况是不行的,但是方法中多出路径中没有的变量则没有影响,只是参数没用

        [WebInvoke(UriTemplate = "/Clients/{id}", Method = "DELETE", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        Client DeleteClient(string id,string name);

4.deleteAll

       [WebInvoke(UriTemplate = "/Clients", Method = "DELETE", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        string DeleteAllClients();

5.post,put数组

        [WebInvoke(UriTemplate = "/Client",Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        Client CreateClient(Client client);

        [WebInvoke(UriTemplate = "/Clients", Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        Client[] CreateClients(Client[] client);

        [WebInvoke(UriTemplate = "/Client", Method = "PUT", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        Client UpdateClient(Client client);

        [WebInvoke(UriTemplate = "/Clients", Method = "PUT", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        Client[] UpdateClients(Client[] client);

因为相同类型Method不能有多个相同的UriTemplate,所有将对当个的处理改成client,对多个的处理改成clients。

客户端测试代码放到下一篇客户端部分中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值