正文转自:http://www.cnblogs.com/scy251147/p/3566638.html

前言

传统的Asmx服务,由于坚守SOAP协议,所以回来内容以xml模式社团。并且客户端需要添加服务端引用才能接纳(即使看出网络上早已提供了那上头的Dynamic
Proxy,不过并未这种方法便捷),所以给开发和部署带来了不小的麻烦。并且当服务过多的时候,生成的引用文件会很大,在此之前项目的一个引用文件光引用代码都有5000多行,全部在一个类中。确实不便利维护。

据悉以上几点,就专门探究了一晃基于Restful的劳动支出,当时光景有二种框架,一个是WCF
Restful Service(Service),另一个是Asp.net Web
API。由于对WCF相比较熟识一些,所以就分选了前者。

Restful Service(Service)及其有关

说到Restful
Service(Service),不得不提到其中的Rest这个第一字。它是用于创设分布式超文本媒体的一种架构情势,我们得以因而正规的HTTP(GET,POST,PUT,DELETE)操作来构建基于面向资源的软件架构格局(Resource-Oriented
Architecture
(ROA)
)。它是单独于其余技术仍旧平台的,所以人们时时将符合这种操作规范的劳动称为“RESTful
services”。因为WCF能够构建符合这种专业的服务,所以大家通常称之为 WCF
Restful Services。

鉴于传统的WCF
Service可以应用tcp,net.msmq,http等协议进行数据交流,并且动用了RPC(Remote
Procedure
Call)的干活办法,客户端需要添加对服务端的引用才能完成。可是WCF Restful
瑟维斯(Service)(Service)完全接纳Http协议来展开,并且无需添加客户端引用,所以方便广大。

服务端开发一瞥

下边以体育场馆的例证来做具体的验证。

打开VS2010,新建一个WCF REST Service(Service)Application项目,然后在项目中,添加一个BookService.cs用于拍卖逻辑操作,再添加一个BookEntity.cs用于提供实体类。

开辟Global.asax,可以看看如下代码:

   1:   void Application_Start(object sender, EventArgs e)

   2:   {

   3:      RegisterRoutes();

   4:   }

   5:   

   6:   private void RegisterRoutes()

   7:   {

   8:      RouteTable.Routes.Add(new ServiceRoute("BookService", new WebServiceHostFactory(), typeof(BookService)));

   9:   }

 

其中RegisterRoutes是设定服务启动的入口点的。

接下来是BookEntity实体类的集体办法:

   1:   public class BookEntity

   2:   {

   3:          public int BookID { get; set; }

   4:   

   5:          public string BookName { get; set; }

   6:   

   7:          public decimal BookPrice { get; set; }

   8:   

   9:          public string BookPublish { get; set; }

  10:   }

那里自己就不用多说了,实体类包含图书序号,图书名称,图书价格,出版单位多少个特性。

下一场就是我们的主题内容:

   1:      [ServiceContract]

   2:      [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

   3:      [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

   4:      public class BookService

   5:      {

   6:          public BookService()

   7:          {

   8:              bookList = new List<BookEntity>();

   9:              BookEntity book = new BookEntity();

  10:              book.BookID = 1;

  11:              book.BookName = "大话设计模式";

  12:              book.BookPrice = (decimal)45.2;

  13:              book.BookPublish = "中国邮电出版社";

  14:              bookList.Add(book);

  15:   

  16:              BookEntity book1 = new BookEntity();

  17:              book1.BookID = 2;

  18:              book1.BookName = "测试用例";

  19:              book1.BookPrice = (decimal)21.0;

  20:              book1.BookPublish = "清华大学出版社";

  21:              bookList.Add(book1);

  22:   

  23:              BookEntity book2 = new BookEntity();

  24:              book2.BookID = 3;

  25:              book2.BookName = "Rework";

  26:              book2.BookPrice = (decimal)15.4;

  27:              book2.BookPublish = "Wrox pulishment";

  28:              bookList.Add(book2);

  29:          }

  30:   

  31:          private static List<BookEntity> bookList;

  32:   

  33:          [WebInvoke(Method = "GET"

  34:              , ResponseFormat = WebMessageFormat.Json

  35:              , BodyStyle = WebMessageBodyStyle.Bare   //不需要任何修饰,否则生成的json无法解析

  36:              , UriTemplate = "/?bookID={bookID}")]  //只接收string类型,如果是其他类型,需要按照 /?para={parameter}的方式来组织。

  37:          public BookEntity Get(int bookID)

  38:          {

  39:              return bookList.Where(p => p.BookID == bookID).FirstOrDefault();

  40:          }

  41:   

  42:          [WebInvoke(Method = "GET"

  43:              , ResponseFormat = WebMessageFormat.Json

  44:              , BodyStyle = WebMessageBodyStyle.Bare

  45:              , UriTemplate = "/")]

  46:          public List<BookEntity> GetALL()

  47:          {

  48:              return bookList;

  49:          }

  50:   

  51:            [WebInvoke(Method = "POST"

  52:              , ResponseFormat = WebMessageFormat.Json

  53:              , BodyStyle = WebMessageBodyStyle.Bare

  54:              , UriTemplate = "/")]

  55:          public bool Update(BookEntity book)

  56:          {

  57:              BookEntity query = (from p in bookList where p.BookID == book.BookID select p).FirstOrDefault();

  58:              bookList.Remove(query);

  59:              bookList.Add(book);

  60:              return true;

  61:            }

  62:   

  63:           [WebInvoke(Method = "PUT"

  64:              , ResponseFormat = WebMessageFormat.Json

  65:              , BodyStyle = WebMessageBodyStyle.Bare

  66:              , UriTemplate = "/")]

  67:          public bool Add(BookEntity book)

  68:          {

  69:              bookList.Add(book);

  70:              return true;

  71:          }

  72:   

  73:          [WebInvoke(Method = "DELETE"

  74:              , ResponseFormat = WebMessageFormat.Json

  75:              , BodyStyle = WebMessageBodyStyle.Bare

  76:              , UriTemplate = "/")]

  77:          public bool Delete(BookEntity book)

  78:          {

  79:              BookEntity bookCurrent = (from p in bookList where p.BookID == book.BookID select p).FirstOrDefault();

  80:              return bookList.Remove(bookCurrent);

  81:          }

  82:      }

里头,Method
方法首假诺评释可以承受客户端的呼吁类型,这里有四种:GET,POST,PUT,DELETE,其中GET为呼吁数据,POST为改进数据,PUT为新增多少,DELETE代表着删除数据。

接下来ResponseFormat
则表示着回去的数据社团,假假若Json则注脚客户端会接收到Json数据,假使是XML则声明客户端会接收到XML协会的数码。BodyStyle
代表回到数据的包装对象,如果是Bare则讲明数据无任何包装,原生数据再次来到;淌倘诺Wrapped则注明数据会在最外层包装一个当下函数名称加上Result的套。比如对于Delete对象,则会回来
DeleteResult:{******},会导致DataContractJsonSerializer无法举行反体系化。

UriTemplate
重要用以指定操作的URI路径,只要用户输入了官方途径并运用了天经地义的请求情势,就会触发该函数。

终极说到的就是URI后边跟的参数的题材,由于函数只可以承受string类型的,所以只要传入参数是string类型,则可以运用UriTemplate
= “{bookID}”的门道,反之,则需要丰盛/?param1={paramname}的措施,比如自己代码中动用的是:UriTemplate
= “/?bookID={bookID}”。

当一切都弄好以后,让大家运行一下,访问如下路径,就足以博得结果:

http://localhost:45345/BookService/

收获的结果如下:

[{"BookID":1,"BookName":"大话设计模式","BookPrice":45.2,"BookPublish":"中国邮电出版社"},{"BookID":2,"BookName":"测试用例","BookPrice":21,"BookPublish":"清华大学出版社"},{"BookID":3,"BookName":"Rework","BookPrice":15.4,"BookPublish":"Wrox pulishment"}]

 假设访问http://localhost:45345/BookService/?bookID=1,则会得到如下的结果:

{"BookID":1,"BookName":"大话设计模式","BookPrice":45.2,"BookPublish":"中国邮电出版社"}

客户端支出一瞥

发端测试成功后,让我们来开展一下圆满的测试。

率先,在项目中,我们新建一个Asp.net WebForm
Application,用于做测试工作。

接下来,在Default.aspx.cs中,针对GET操作,我们添加如下代码:

   1:   private void GetBookByID(string id)

   2:          {

   3:              WebClient proxy = new WebClient();

   4:              string serviceURL = string.Empty;

   5:              DataContractJsonSerializer obj ;

   6:              if (string.IsNullOrEmpty(id))

   7:              {

   8:                  serviceURL = string.Format("http://localhost:45345/BookService/");

   9:                  obj = new DataContractJsonSerializer(typeof(List<BookEntity>));

  10:              }

  11:              else

  12:              {

  13:                  serviceURL = string.Format("http://localhost:45345/BookService/?bookID=" + id);

  14:                  obj = new DataContractJsonSerializer(typeof(BookEntity));

  15:              }

  16:              byte[] data = proxy.DownloadData(serviceURL);

  17:              Stream stream = new MemoryStream(data);

  18:              var result = obj.ReadObject(stream);

  19:              List<BookEntity> list=new List<BookEntity>();

  20:              if (result is BookEntity)

  21:                  list.Add(result as BookEntity);

  22:              else if (result is List<BookEntity>)

  23:                  list = result as List<BookEntity>;

  24:              GridView1.DataSource = list;

  25:              GridView1.DataBind();

  26:          }

在上述代码中,DataContractJsonSerializer
是WCF提供的一个体系化类,用于将对象系列化或者反系列化。

写好将来,我们点击界面按钮,出现了以下的结果:

XML 1XML 2

本着PUT操作,也就是充裕操作,我们抬高如下代码:

   1:  BookEntity bookEntity = new BookEntity();

   2:              bookEntity.BookID = Int32.Parse(txtBookID.Text);

   3:              bookEntity.BookName = txtBookName.Text;

   4:              bookEntity.BookPrice = decimal.Parse(txtBookPrice.Text);

   5:              bookEntity.BookPublish = txtBookPublish.Text;

   6:   

   7:              DataContractJsonSerializer obj = new DataContractJsonSerializer(typeof(BookEntity));

   8:              MemoryStream ms = new MemoryStream();

   9:              obj.WriteObject(ms, bookEntity);

  10:              byte[] byteSend = ms.ToArray();

  11:              ms.Close();

  12:   

  13:              string serviceURL = string.Format("http://localhost:45345/BookService");

  14:   

  15:              WebClient test = new WebClient();

  16:              test.Headers.Add("Content-Type", "application/json");

  17:              test.Headers.Add("ContentLength", byteSend.Length.ToString());

  18:              

  19:   

  20:              byte[] responseData = test.UploadData(serviceURL, "PUT", byteSend);

  21:   

  22:              string result = Encoding.GetEncoding("UTF-8").GetString(responseData);

  23:              lblLog.Text = result;

在做这步的时候,需要小心,test.Headers.Add(“Content-Type”, “application/json”)
和test.Headers.Add(“ContentLength”,
byteSend.Length.ToString())需要添加,否则会导致Http 400
重返的不当。并且,向服务端传递实体的时候,能够透过利用UploadData的形式来进展,假使数据量过大,可以考虑采用异步形式传送。

接下去的POST和DELETE方法和地点类似,我都贴一下:

POST方法:

   1:   BookEntity bookEntity = new BookEntity();

   2:              bookEntity.BookID = Int32.Parse(txtBookID.Text);

   3:              bookEntity.BookName = txtBookName.Text;

   4:              bookEntity.BookPrice = decimal.Parse(txtBookPrice.Text);

   5:              bookEntity.BookPublish = txtBookPublish.Text;

   6:   

   7:              DataContractJsonSerializer obj = new DataContractJsonSerializer(typeof(BookEntity));

   8:              MemoryStream ms = new MemoryStream();

   9:              obj.WriteObject(ms, bookEntity);

  10:              byte[] byteSend = ms.ToArray();

  11:              ms.Close();

  12:   

  13:              string serviceURL = string.Format("http://localhost:45345/BookService");

  14:   

  15:              WebClient test = new WebClient();

  16:              test.Headers.Add("Content-Type", "application/json");

  17:              test.Headers.Add("ContentLength", byteSend.Length.ToString());

  18:              

  19:              byte[] responseData = test.UploadData(serviceURL, "POST", byteSend);

  20:   

  21:              string result = Encoding.GetEncoding("UTF-8").GetString(responseData);

  22:              lblLog.Text = result;

DELETE方法:

   1:   BookEntity bookEntity = new BookEntity();

   2:              bookEntity.BookID = Int32.Parse(txtBookID.Text);

   3:   

   4:              DataContractJsonSerializer obj = new DataContractJsonSerializer(typeof(BookEntity));

   5:              MemoryStream ms = new MemoryStream();

   6:              obj.WriteObject(ms, bookEntity);

   7:              byte[] byteSend = ms.ToArray();

   8:              ms.Close();

   9:   

  10:              string serviceURL = string.Format("http://localhost:45345/BookService");

  11:   

  12:              WebClient test = new WebClient();

  13:              test.Headers.Add("Content-Type", "application/json");

  14:              test.Headers.Add("ContentLength", byteSend.Length.ToString());

  15:              

  16:   

  17:              byte[] responseData = test.UploadData(serviceURL, "DELETE", byteSend);

  18:   

  19:              string result = Encoding.GetEncoding("UTF-8").GetString(responseData);

  20:              lblLog.Text = result;

最终取得的功效图如下:

XML 3

(新增记录)

XML 4

(更新记录)

XML 5

(删除记录)

 成文仓促,难免有误,还请提出,在此谢过。

源代码下载

点击下载源代码  

 

Edit:基于本办法构建的Android服务一度在利用中。后续继续跟进各类应用音讯。

在StackOverFlow问答如下:点击这里查看

 看评论中提到了IContract问题,由于这是Restful
Service(Service),不是基于RPC形式,所以没必要拔取的。不过用上去也没错。

 

 

分类: WCF
点滴记录

相关文章

网站地图xml地图