对于.NET的分布式应用开发,能够供我们采用的技艺和框架相比较多,例如webservice,.net
remoting,MSMQ,WCF等等技术。对于这一个技能很四个人都不会陌生,即时没有深入的问询,然则毫无疑问听说过,每种技术都各有优势和适用范围,没有断然的优劣,只有相对的适当程度。可是可惜了,明天大家讲课的焦点不是那二种技术,昨天第一助教的是ASP.NET
WebAPI。
对于ASP.NET
WebAPI的优势和特点,在那边就不讲了,须要选取的本来就会挑选,也不须求自我浪费篇幅去教师那一个,那篇博文主要助教ASP.NET
WebAPI中的HTTP音讯的构造和处理信息的基本目的。
一.WebAPI的HTTP概述:
有关HTTP协议的相干内容在这边就不做牵线,在小编后面的博文中早就做过介绍,现在提供一下地址,因为过多的废话就是浪费时间,我就姑且看那篇博文的读者已经对HTTP协议和WebAPI都具有明白。博文地址:
http://www.cnblogs.com/pengze0902/p/5976388.html
http://www.cnblogs.com/pengze0902/p/6224792.html
http://www.cnblogs.com/pengze0902/p/6230105.html
1.在.NET4.5事先的版本中,处理HTTP的中坚目的:
(1).在客户端:System.Net.HttpWebRequest用于开始化HTTP请求,处理相关的响应; System.Net.HttpWebResponse处理HTTP响应头和数码读取的物色。
(2).在劳动器端:System.Web.HttpContext,System.Web.HttpRequest,System.Web.HttpResponse类用在ASP.NET上下文中,代表单个请求和响应。System.Net.HttpListenerContext类,提供对HTTP请求和响应对象的拜会。
2.在.NET4.5本子中,处理HTTP的焦点目标:
(1).在客户端和劳务器端使用同一的类。(HttpRequestMessage和HttpResponseMessage对象中不分包上下文新闻,所以可以在服务器和客户端共用。)
(2).由于在.NET4.5中引入了TAP(异步职务模型),所以在新的HTTP模型中,处理HTTP请求的方式可以运用async和awit完成异步编程。(可以省略便捷的兑现异步编程)
我们对于新旧的HTTP编程模型时,会很简单的觉察在新本子的HTTP模型中,无论是编程的难度和代码编写的精简度,已经实施的频率都是很高的。在对于Web项目的支出中,大家对HTTP知识的问询是少不了的,对于ASP.NET的HTTP处理的法则在这边就不做具体的牵线,网上也有相比较多的文章可供阅读和询问。
对于ASP.NET的HTTP处理格局的打听,是自个儿在付出微信公众平台时更是读书的,微信公众平台提供了对外访问的接口,大家的顺序和服务器对微信服务器的接口进行呼吁访问,微信服务器获取HTTP请求后,重回处理结果,本地服务器获取再次回到结果。那样一个请求-响应格局,组成一个对话。对于微信公众平台的付出对于众多刚学习.NET的人的话多少高大(当然那是相持而言),即时开发过很频仍那些类型的先后的人(调用第三方接口的费用)也不必然可以很清晰的知情那一个里面的法则,小编以为对于如此的第三方平台的付出,其关键的基本部分就是对此HTTP协议的拍卖,建立请求、获取响应信息和剖析音信那三大步子,重临的信息内容相似为json或者xml,获取响应信息后,重即使对消息内容的反连串化,得到音信的实业新闻,进而在先后中国和越南社会主义共和国来越处理。
在WeAPI中音讯的发生和分析,以及音信的格式都是足以动态的创始和商谈,下边大家尤其的刺探完毕这一进度的中坚目标。
二.WebAPI的HTTP新闻分析:
HTTP协议的行事形式是在客户端和服务器之间沟通请求和响应信息,那么那也就可以阐明HTTP的骨干就是音讯,对于“音信”的打听,大家借使精通信息分为“信息底部”和“新闻内容”,大家接下去的对新HTTP编程模型的介绍的焦点就是“新闻头部”和“音信内容”。
在命名空间System.Net.Http中,具有多少个要旨目标:HttpRequestMessage和HttpResponseMessage。三个目的的构造如下图:
以上重点教学了HttpRequestMessage对象和HttpResponseMessage对象涵盖的第一内容,请求和响应信息都得以分包一个可选的音讯正文,两中音讯类型以及新闻内容,都足以行使响应的标头。接下来具体通晓部分音讯的布局。
1.HttpRequestMessage对象解析:
(1).HttpRequestMessage主要质量和办法概述:
名称 | 说明 |
Version | 获取或设置 HTTP 消息版本 |
Content | 获取或设置 HTTP 消息的内容 |
Method | 获取或设置 HTTP 请求信息使用的 HTTP 方法 |
RequestUri | 获取或设置 HTTP 请求的 Uri |
Headers | 获取 HTTP 请求标头的集合 |
Properties | 获取 HTTP 请求的属性集 |
ToString | 返回表示当前对象的字符串 |
该对象主要用于表示 HTTP
请求信息。对于该目的的这个属性和办法,半数以上应该都不会陌生,因为一个HTTP新闻中首要包罗底部、新闻内容等等,在那边关键介绍一个质量Properties,该属性并不属于别的专业的HTTP新闻,当信息传输时,不会保留该属性。
(2).Properties属性解析:
[__DynamicallyInvokable]
public IDictionary<string, object> Properties
{
[__DynamicallyInvokable]
get
{
if (this.properties == null)
{
this.properties = new Dictionary<string, object>();
}
return this.properties;
}
}
有上述的代码可以很明朗的看来该属性只有一个只读属性,并回到一个IDictionary<string,
object>。当音讯在服务器或者客户端本地开展拍卖时,该属性用于保存附加的新闻音信。该属性只是一个通用的容器,保存本地新闻属性。(与接受新闻的连天相关的客户端认证;将新闻与布局路由进行匹配,得到的路由数据)
2.HttpResponseMessage目标解析:
(1).HttpRequestMessage主要品质和方法概述:
名称 | 说明 |
EnsureSuccessStatusCode | 如果 HTTP 响应的 IsSuccessStatusCode 属性为 false, 将引发异常 |
StatusCode | 获取或设置 HTTP 响应的状态代码 |
ReasonPhrase | 获取或设置服务器与状态代码通常一起发送的原因短语 |
RequestMessage | 获取或设置导致此响应消息的请求消息 |
IsSuccessStatusCode | 获取一个值,该值指示 HTTP 响应是否成功 |
对于该对象的片段性质没有列举,因为在HttpRequestMessage对象已经介绍,如:Version、Content、Headers等,该目标主要用来表示
HTTP 响应音讯。在那里紧要介绍StatusCode属性。
C++, (2).StatusCode属性:
[__DynamicallyInvokable]
public HttpStatusCode StatusCode
{
[__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
get
{
return this.statusCode;
}
[__DynamicallyInvokable]
set
{
if ((value < ((HttpStatusCode) 0)) || (value > ((HttpStatusCode) 0x3e7)))
{
throw new ArgumentOutOfRangeException("value");
}
this.CheckDisposed();
this.statusCode = value;
}
}
StatusCode属性为枚举属性,该属性可读可写,对于状态码那么些定义,很多人都是相比较了然的,在HTTP协议中,状态码首如若代表在新闻的伸手在服务器中处理的结果,状态有2XX,3XX,4XX,5XX等等,具体表示的意思就不再描述。
3.HTTP模型音讯标头解析:
在HTTP中,请求和响应音讯,以及新闻内容本身,都足以行使称为标头的附加字段,包蕴越多的信息。
(1).标头分类:
标头名称 | 描述 | HTTP模型标头容器类 |
User-Agent | 为请求提供扩展信息,描述产生这个请求的应用程序 | HttpRequestHeaders |
Server | 为响应提供关于源服务器软件的扩展信息 | HttpResponseHeaders |
Content-Type | 定义请求或响应有效载荷正文中,资源表示使用的媒体类型 | HttpContentHeaders |
(2).HttpHeaders抽象类分析:
名称 | 描述 |
Add | 添加指定的标头及其值到 HttpHeaders 集合中。 |
TryAddWithoutValidation | 返回一个值,该值指示指定标头及其值是否已添加到HttpHeaders 集合,而未验证所提供的信息。 |
Clear | 从 HttpHeaders 集合中移除所有标头。 |
Remove | 从HttpHeaders集合中移除指定的标头。 |
GetValues | 返回存储在HttpHeaders 集合中所有指定标头的标头值。 |
Contains | 如果指定标头存在于 HttpHeaders 集合则返回。 |
ToString | 返回表示当前 HttpHeaders对象的字符串。 |
HttpHeaders是一个抽象类,HttpRequestHeaders、HttpResponseHeaders、HttpContentHeaders多少个类继承了此类。接下来大家来打探一下Add()方法:
[__DynamicallyInvokable]
public void Add(string name, string value)
{
HeaderStoreItemInfo info;
bool flag;
this.CheckHeaderName(name);
this.PrepareHeaderInfoForAdd(name, out info, out flag);
this.ParseAndAddValue(name, info, value);
if (flag && (info.ParsedValue != null))
{
this.AddHeaderToStore(name, info);
}
}
Add()方法具有八个重载版本,该格局可以向容器添加标头,如若要拉长的标头有标准名,在增进前面标头值会进展表明。Add方法还会阐明标头是不是可以有多少个值。
4.HTTP音讯内容分析:
在.NET4.5版本的HTTP模型中,HTTP音讯的正文由抽象基类HttpContent表示,HttpResponseMessage和HttpRequestMessage对象都富含一个HttpContent类型的Content属性。
(1).HttpContent首要质量和办法:
名称 | 描述 |
ReadAsByteArrayAsync | 以异步操作将 HTTP 内容写入字节数组。 |
SerializeToStreamAsync | 以异步操作将 HTTP 内容序列化到流。 |
CopyToAsync | 以异步操作将 HTTP 内容写入流。 |
LoadIntoBufferAsync | 以异步操作将 HTTP 内容序列化到内存缓冲区。 |
CreateContentReadStreamAsync | 以异步操作将 HTTP 内容写入内存流。 |
TryComputeLength | 确定 HTTP 内容是否具备有效的字节长度。 |
Headers | 根据 RFC 2616 中的定义,获取内容标头。 |
(2).CopyToAsync()方法分析:
[__DynamicallyInvokable]
public Task CopyToAsync(Stream stream, TransportContext context)
{
Action<Task> continuation = null;
this.CheckDisposed();
if (stream == null)
{
throw new ArgumentNullException("stream");
}
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
try
{
Task task = null;
if (this.IsBuffered)
{
task = Task.Factory.FromAsync<byte[], int, int>(new Func<byte[], int, int,
AsyncCallback, object, IAsyncResult>(stream.BeginWrite), new Action<IAsyncResult>(stream.EndWrite),
this.bufferedContent.GetBuffer(), 0, (int) this.bufferedContent.Length, null);
}
else
{
task = this.SerializeToStreamAsync(stream, context);
this.CheckTaskNotNull(task);
}
if (continuation == null)
{
continuation = delegate (Task copyTask) {
if (copyTask.IsFaulted)
{
tcs.TrySetException(GetStreamCopyException(copyTask.Exception.GetBaseException()));
}
else if (copyTask.IsCanceled)
{
tcs.TrySetCanceled();
}
else
{
tcs.TrySetResult(null);
}
};
}
task.ContinueWithStandard(continuation);
}
catch (IOException exception)
{
tcs.TrySetException(GetStreamCopyException(exception));
}
catch (ObjectDisposedException exception2)
{
tcs.TrySetException(GetStreamCopyException(exception2));
}
return tcs.Task;
}
在运用音信内容时,须要运用HtppContent的点子或者扩充方法。在HttpContent中动用CopyToAsync()方法以推送方式访问原本的音信内容,由艺术代码可以观望,该办法接受三个参数,一个是流对象,一个是关于传输的新闻(例如,通道绑定),此参数可以为
null。该方法可以把音讯内容写入到那些流中。
在该措施的贯彻代码中
创立了一个TaskCompletionSource<object>的泛型对象,该对象表示未绑定到委托的 Task<TResult> 的成立者方,并经过 Task 属性提供对使用者方的造访。SerializeToStreamAsync方法将盛传的流对象连串化,该情势为异步方法。
大家必要专注的几点,首要为委托的创设和运用,在C#中,尽量使用有.NET提供的委托类,不要自己去创立。还有一些就是在先后中对足够的处理格局,很是的抓获具有层次性,并且调用了自定义的一个分外处理方式TrySetException。
(2).ReadAsStreamAsync()方法分析:
在赢得原始音讯内容时,除了调用上边介绍的措施外,还足以调用ReadAsStreamAsync()方法以拉取的艺术访问原本的消息内容。
在HttpContent中包罗有其它三个类似的办法,ReadAsStringAsync()和ReadAsByteArrayAsync()异步的提供音信内容的缓冲副本,ReadAsByteArrayAsync()再次回到原始的字节内容,ReadAsStringAsync()将内容解码为字符串再次来到。
三.DotNet中新旧HTTP模型解析:
1..NET4.5从前版本创造HTTP POST请求实例:
public static string HttpPost(string postUrl, string postData)
{
if (string.IsNullOrEmpty(postUrl))
throw new ArgumentNullException(postUrl);
if (string.IsNullOrEmpty(postData))
throw new ArgumentNullException(postData);
var request = WebRequest.Create(postUrl) as HttpWebRequest;
if (request == null)
throw new ArgumentNullException("postUrl");
try
{
var cookieContainer = new CookieContainer();
request.CookieContainer = cookieContainer;
request.AllowAutoRedirect = true;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
var data = Encoding.UTF8.GetBytes(postData);
request.ContentLength = data.Length;
var outstream = request.GetRequestStream();
outstream.Write(data, 0, data.Length);
outstream.Close();
//发送请求并获取相应回应数据,获取对应HTTP请求的响应
var response = request.GetResponse() as HttpWebResponse;
if (response != null)
{
var instream = response.GetResponseStream();
var content = string.Empty;
if (instream == null)
{
return content;
}
using (var sr = new StreamReader(instream, Encoding.UTF8))
{
content = sr.ReadToEnd();
}
return content;
}
}
catch (ArgumentException arex)
{
throw arex;
}
catch (IOException ioex)
{
throw ioex;
}
return null;
}
2..NET4.5版本创设HTTP POST请求实例:
async static void getResponse(string url)
{
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.GetAsync(url))
{
using (HttpContent content = response.Content)
{
string myContent = await content.ReadAsStringAsync();
}
}
}
}
async static void postResponse(string url)
{
while (true)
{
IEnumerable<KeyValuePair<string, string>> queries = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string> ("test","test")
};
HttpContent q = new FormUrlEncodedContent(queries);
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.PostAsync(url, q))
{
using (HttpContent content = response.Content)
{
string myContent = await content.ReadAsStringAsync();
Console.WriteLine(myContent);
}
}
}
}
}
四.总结:
以上首要教师了.NET4.5从前和今后版本对HTTP编程形式的局地情节, 两者的关键不相同在于.NET4.5版本此前的HTTP编程模型会区分客户端和服务器,两者接纳的靶子存在不一样,已毕的原理上即使存在一定的相似性,但是利用的类却不比。.NET4.5将来的本子中,对象的应用没有客户端和服务器之分,两者可以共用。