WCF REST 工作总结(二)

上一篇 我们搭建了WCF REST 的服务 平且通过 三种方式发送get请求  实现了获取json  没看过的朋友可以先去看下----REST 工作总结一

今天主要写下  POST等其他方式 发送请求 以及 流方式 文件的上传与下载

 

一.Post 提交数据

先来想下 POST和Get 的不同   Get 方式 我们直接通过 url  来传递参数   先来看下我们的  创建方法吧

 

   [WebInvoke(UriTemplate = "Tasks/Add", Method = "POST", RequestFormat = WebMessageFormat.Json)]
void Create(PocoTask pocoTask);


我们需要接受一个实体类   格式为json格式  这就再次出现上文的问题  我们的客户端没有实体类  没法把实体类序列化为json  难道要自己拼接json么? 当然不用。那简直太痛苦了。

这里给大家推荐 Json.Net   这里有两个类 可以帮我们完成  单个实体的转换 以及集合实体的转换 分别是 JObject 和 JArray 

我们只需声明这两个类后  .toString 就可得到他的json格式了  很方便吧~ 看代码

这里完全可以不用dynamic的  像注释那样的写法就行 这样即使服务器不支持.net4.0 也可以使用的

知道了如何构建POST 提交的数据 就开始实现POST提交吧~ 上代码 依然是三种方式 放一起 对比

这三个方式 个人很推荐 第三种 也是目前最新的 .net4.5里集成的 访问REST 非常的方便 因为他支持 直接点出来 PUT 以及 DELETE请求

简直是为rest 量身定制的~~ 看下 PUT请求

这里需要注意下  因为我们发送的是json 不论是哪种发送请求的方式 都要记得 设置ContentType=application/json

否则会抛出 HTTP 400的错误  400-错误的请求 很多都是客户端请求不正确造成的  所以一般出来400错误 可以重点检查下 客户端请求的问题

因为 PUT 与 DELETE 和 POST 基本类似  我就不上代码了 

二.REST 的文件上传 与下载

流文件的上传和下载 

先来看服务端的接口与实现

我们要实现三个功能

1. 展示一张图片

2.下载一个文件

3.上传一个文件

一个一个说 先说展示图片 实现代码

这个是在浏览器中直接打开  比较简单  这里记得设置输出的 ContentType  有时我们想打开的是别的格式 这里有个小方法  根据文件扩展名获得输出的ContentType

也就是上面用到的GetContentType方法  在园子的知识库里发现的 GetContentType

客户端 非常简单 直接引用连接即可

2.下载

上面的是直接把文件显示在浏览器中 如果我们希望下载资源呢 方法也很简单和以前的方法是一样的  直接上代码

文件下载
 public void GetExecl(string execlName)
{
string folder = System.Web.Hosting.HostingEnvironment.MapPath("~/Files");
var FullFileName = Path.Combine(folder, execlName);
if (File.Exists(FullFileName))
{
FileInfo DownloadFile = new FileInfo(FullFileName);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.Buffer = false;
HttpContext.Current.Response.ContentType = "application/octet-stream";
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(DownloadFile.FullName, System.Text.Encoding.ASCII));
HttpContext.Current.Response.AppendHeader("Content-Length", DownloadFile.Length.ToString());
HttpContext.Current.Response.WriteFile(DownloadFile.FullName);

HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
}
}

3.上传
这个文件上传 才是重点要说的  折腾了好久~ 

首先要说的是  一定要记得配置文件 如果用REST 模版 配置方法如下

  <system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<standardEndpoints >
<webHttpEndpoint >
<!--
Configure the WCF REST service base address via the global.asax.cs file and the default endpoint
via the attributes on the <standardEndpoint> element below
-->
<standardEndpoint name="" maxReceivedMessageSize="3000000" defaultOutgoingResponseFormat="Json" helpEnabled="true" automaticFormatSelectionEnabled="true">
<readerQuotas maxArrayLength="300000"/>
</standardEndpoint>

</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>

这样就可以上传大文件了

客户端实现上传很简单 借助 HttpClient

本来写到这  以为上传很简单的就能完成了 结果却弄了好久 

先说下以前的写法

以前这样 都能成功  谁知道这次移到 REST WCF 中  竟然报错  发现不能读取Stream.Length   在这里问下各位高手 ~为什么读取Stream.Length 会报错?

CSDN 的  fangxinggood  给了解释 非常感谢

因为它被封装成了MessageBodyStream,就像WCF Streamed的数据一样,Length是不支持的。WCF里是客户端一边传服务端一边收。到达服务端开始写IO时,流并没有全部传输完,所以 MessageBodyStream不支持Length。但REST时是Http协议,所以其实Stream已经全部到达服务端了。如果你想取长度,可以 用: var len = WebOperationContext.Current.IncomingRequest.ContentLength;来获得。

如图

最后就会抛出Http 400的错误

百思不得其解  只好换了另一种方法这种方法不需要 长度length

可是却发现在 转化成byte 这次是报错  输入的不是有效的 Base-64 字符串,因为它包含非 Base-64 字符、两个以上的填充字符,或者填充字符间包含非空白字符。

再次请问原因?  希望遇到过的朋友告知

解决办法

后来 通过谷歌 发现另外一种 获得长度的方法 在WCF REST里   这样就能用第一种方法了 

把最早方法里的

  long ByteLength=stream.Length;

  换成

  long ByteLength = WebOperationContext.Current.IncomingRequest.ContentLength;

  这样就可以得到长度了  上传问题也就解决了~~

 这里说下 如果上传的是图片 有个很简单的方法   核心代码 简单两行即可~

三.Session与Cookie

 在WCF 里  是可以使用session的  但是在REST 的WCF 里  貌似却不能使用session 查了些资料 没有发现使用session的办法 

 可能是因为使用session会让服务器和客户端耦合。 后来找到了 REST 常见误区  http://www.prescod.net/rest/mistakes/

 里面提到了一条  session 是无关紧要的。

 cookie 还是可以正常使用的  这里说下 客户端读取cookie的方法  webclient 貌似不能读到 要使用更加灵活的 HttpWebRequest

主要是这两句

     CookieContainer Cookie = new CookieContainer();
     request.CookieContainer = Cookie;

四.总结

在做这方面的工作  把经验分享给大家 也希望会的人 能解答下我问中的问题~~

REST WCF  体现了ROA 面向资源编程  感觉更好了解耦了客户端与服务端  而且调用 REST 服务  也简单了很多 没有了代理等 效率也提高了 喜欢这种风格的方式

参考:

http://blog.csdn.net/fangxinggood/article/details/6235662

原文:

http://www.cnblogs.com/wlflovenet/archive/2011/10/28/WCFREST2.html

posted on 2011-10-30 11:09  wlf  阅读(15000)  评论(45编辑  收藏  举报