zoukankan      html  css  js  c++  java
  • Wcf Restful Service服务搭建

    • 目的

    使用Wcf(C#)搭建一个Restful Service

    • 背景

    最近接到一个项目,客户要求使用Restful 方式接收到数据,并对数据提供对数据的统计显示功能,简单是简单,但必须要使用Restful方式,客户端传递数据就必须使用Rest ful的格式的url,提交方式为Post。

    其实在之前的公司里边就开发过一个restful服务,但只记得自己使用的wcf,而今已经忘记的差不多了,还以为只是简单的搭建一个wcf就可以,今天起初就创建了一个wcf项目,发现wcf项目http://localhost:6001/Test.svc好像很让人纠结就是这个url就是多出一个。svc,wsd什么之类的,根本就不是restful,后来上网上搜到原来我们之前不是用的简单的wcf工程,而是通过Wcf rest service template工程创建的。

    • 创建Wcf rest service template工程:

    在vs 新建工程-》online templates-》在搜索框中输入Wcf rest service template-》

    创建好工程的工程:

    • 这个工程值得注意的有以下地方:

    1, Gobal.asax文件中的代码:

     1  public class Global : HttpApplication
     2     {
     3         void Application_Start(object sender, EventArgs e)
     4         {
     5             RegisterRoutes();
     6         }
     7 
     8         private void RegisterRoutes()
     9         {
    10             // Edit the base address of Service1 by replacing the "Service1" string below
    11             RouteTable.Routes.Add(new ServiceRoute("Service1", new WebServiceHostFactory(), typeof(Service1)));
    12         }
    13     }

    这里边是注册了url访问 route,这个访问格式就包含一下集中restful访问类型:

    2.访问方式

    备注:我默认的url host url为:http://localhost:6001/

    访问url:http://localhost:6001/Service1           提交方式:GET      调用函数为:GetCollection

    访问url:http://localhost:6001/Service1           提交方式:POST    调用函数为:Create

    访问url:http://localhost:6001/Service1/1        提交方式:Get       调用函数为:Get(...) 

    访问url:http://localhost:6001/Service1/1        提交方式:PUT       调用函数为:Update(...)

    访问url:http://localhost:6001/Service1/1        提交方式:PUT       调用函数为:Delete(...)
    3.怎么注册访问方式

    [WebGet(UriTemplate = "")]

    List<SampleItem> GetCollection()

    [WebInvoke(UriTemplate = "", Method = "POST")]
    SampleItem Create(SampleItem instance)

    [WebGet(UriTemplate = "{id}")]
    SampleItem Get(string id)

    [WebInvoke(UriTemplate = "{id}", Method = "PUT")]
    SampleItem Update(string id, SampleItem instance)

    [WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
    void Delete(string id) 

    其实我们可以注意到这些"访问url"访问到的“调用的函数”上的注解:

    指定了访问url为:http://localhost:6001/Service1 

    WebGetAttribute

     a. 决定了提交方式为Get,

     b. UriTemplate ,决定了是否在http://localhost:6001/Service1后边追加其他路径

     c. 其他参数RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Json等

    WebInvokeAttribute

     a.UriTemplate ,决定了是否在http://localhost:6001/Service1后边追加其他路径

     b.Method,决定了提交方式,可选参数包含Get,Post,Put,Delete,当然也支持Header等其他方式。

    c. 其他参数RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Json等

    • 关于请求、返回数据格式

    REST被受到欢迎原因:

    1,分布式架构

    2,请求、返回格式支持xml,json。

    3,支持异步请求/提交数据,这使得Javascript可以轻松调用RESTful服务。

    A.如果手动配置请求、返回数据格式?

    wcf rest service template内置了简单的注册方式:在上边我们提到的WebGetAttribute,WebInvokerAttribute中都支持参数RequestFormat,ResponseFormat,可以手动的在代码中制定他们的参数类型:

     1  // Summary:
     2     //     An enumeration that specifies the format of Web messages.
     3     public enum WebMessageFormat
     4     {
     5         // Summary:
     6         //     The XML format.
     7         Xml = 0,
     8         //
     9         // Summary:
    10         //     The JavaScript Object Notation (JSON) format.
    11         Json = 1,
    12     }

    B.如果动态配置请求、返回数据格式?

    相比手动配置之下,动态选择格式还是更灵活。打开之前创建的项目,在web.config中,设置:

    <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>

    将automaticFormatSelectionEnabled设置为true

          设置后,我们就可以通过url访问到当前我们可以访问的路径接口等.

    • 测试客户端

    比如我们Restful Service代码如下:

      [WebInvoke(UriTemplate = "Servlet", Method = "POST", ResponseFormat = WebMessageFormat.Json)]
            public string Welcome()
            {
                try
                {
                   // 接收传递的参数信息
                   string param= HttpContext.Current.Request["param"];
    
                   // do somthing 
    
                   // 返回成功操作状态信息
                   return "{"status": 0, "msg": "操作成功!"}"; 
                   
                }
                catch (Exception ex)
                {
                   
                    // 返回失败操作状态信息
                    return "{"status": 1, "msg": "操作失败!"}"; ;
                }
            }

    客户端调试:

    static void Main(string[] args)
            {
                NameValueCollection responseEntity = new NameValueCollection();
                responseEntity.Add("param", "1");
    
                string baseUrl = "http://localhost:6001/TestReceiver/Welcome";
    
                try
                {
                    WebClient webClient = new WebClient();
    
                    // 采取POST方式必须加的header,如果改为GET方式的话就去掉这句话即可 
                    webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
    
                    // 得到返回字符流  
                    byte[] responseData = webClient.UploadValues(baseUrl, "POST", responseEntity);
    
                    // 解码返回值  
                    string byRemoteInfo = Encoding.UTF8.GetString(responseData);
    
                    Console.WriteLine(byRemoteInfo);
    
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(ex.StackTrace);
                }
    
                Console.ReadKey();
            }

      上边我们采用的接收参数的方式是HttpContext.Current.Request.Params["param"]的方式来接收参数,确切说,这种方式在vs的调试模式下是可以接收到参数的,但是在iis上就不是这么好说了(具体问题,我不是太清楚是不是因为我的服务器上没有注册WCF组建的方式(验证方案参考:http://blog.csdn.net/findsafety/article/details/9045721),还是其他问题;具体原因我暂时不能去确认,服务器远程不了,只能明天去确认)。

    • 服务器端在函数的参数中写入要接收的参数信息,作为函数的参数,这种方式是可行的。

      demo:

      

     1 public class Global : HttpApplication
     2 {
     3     void Application_Start(object sender, EventArgs e)
     4     {
     5         RegisterRoutes();
     6     }
     7 
     8     private void RegisterRoutes()
     9     {
    10         // Edit the base address of Service1 by replacing the "Test" string below
    11         RouteTable.Routes.Add(new ServiceRoute("Test", new WebServiceHostFactory(), typeof(Test)));
    12     }
    13 }
    14 
    15 [ServiceContract]
    16 [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    17 [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    18 // NOTE: If the service is renamed, remember to update the global.asax.cs file
    19 public class Test
    20 {
    21     private Logger logger = LogManager.GetCurrentClassLogger();
    22 
    23     [WebInvoke(UriTemplate = "Login", Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest)]
    24     public bool Login(string userName, string userPassword)
    25     {
    26         //模拟登录,实际使用时需数据库访问
    27         if (userName == "huangbo" && userPassword == "123")
    28         {
    29             return true;
    30         }
    31         return false;
    32     }
    33 }
    34 
    35 public class UserInfo
    36 {
    37     public string userName { get; set; }
    38     public string userPassword { get; set; }
    39 }
    40 
    41 class Program
    42 {
    43     static void Main(string[] args)
    44     {
    45         string baseUrl = "http://localhost:6001/Test/Login";
    46 
    47         UserInfo info = new UserInfo
    48         {
    49             userName = "11",
    50             userPassword = "222"
    51         };
    52 
    53         //先访问LoginService,得到授权
    54         var request = (HttpWebRequest)WebRequest.Create(baseUrl);
    55         request.ContentType = "application/json;charset=utf-8";
    56         request.Method = "POST";
    57         request.KeepAlive = true;
    58         //request.ClientCertificates.Add(cert);
    59         //使用JSON.NET将对象序列化成JSON字符串
    60         var requestBody = Newtonsoft.Json.JsonConvert.SerializeObject(info);
    61         byte[] databytes = Encoding.UTF8.GetBytes(requestBody);
    62         request.ContentLength = databytes.Length;
    63         using (var writer = request.GetRequestStream())
    64         {
    65             writer.Write(databytes, 0, databytes.Length);
    66         }
    67         var response = request.GetResponse();
    68         using (var stream = response.GetResponseStream())
    69         {
    70             using (var reader = new StreamReader(stream))
    71             {
    72                 Console.WriteLine(reader.ReadToEnd());
    73             }
    74         }
    75     }
    76 }
    77             

    参考资料:

    http://www.cnblogs.com/xiarifeixue/archive/2011/04/27/restful.html

    http://www.cnblogs.com/bearhb/archive/2012/07/11/2586412.html

    怎么接收参数:

    UserInfo info = new UserInfo
    {
    userName = “user”,
    userPassword = “pwd”
    };

    string strJson=Newtonsoft.Json.JsonConvert.SerializeObject(message);

    byte[] jsonBytes=Encoding.UTF8.GetBytes(strJson);

    test client post method: json string UploadData(string url,string method,byte[] bytes);

    webClient.UploadData("url","Post",jsonBytes);

    mapping WCF Rest Service method: 

     [WebInvoke(UriTemplate = "", Method = "POST",BodyStyle=WebMessageBodyStyle.WrappedRequest)]

     public bool Login(string userName, string userPassword)
    {
      return true;
    }
  • 相关阅读:
    (转)ubuntu 对拍和基本操作
    一个在线翻译LateX的网站
    51nod 1376: 最长递增子序列的数量(二维偏序+cdq分治)
    BZOJ1087: [SCOI2005]互不侵犯King(状态压缩动态规划)
    ZOJ Problem Set
    bzoj2301:[HAOI2011]Problem b(容斥+莫比乌斯反演+分块)
    BZOJ 4318 OSU!期望DP
    CodeForces 235B Let's Play Osu!(概率)
    博客界面美化
    A+B Problem
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/4115056.html
Copyright © 2011-2022 走看看