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;
}
原文地址:https://www.cnblogs.com/yy3b2007com/p/4115056.html