对于.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。几个目的的布局如下图:

json 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属性。

       (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;
        }

json,   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随后的版本中,对象的利用没有客户端和服务器之分,两者可以共用。

相关文章