C++Asp.Net WebAPI宗旨目的解析(三)

 
 对于.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。三个目的的构造如下图:

C++ 1

     
以上重点教学了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将来的本子中,对象的应用没有客户端和服务器之分,两者可以共用。