About the HTTP model in ASP. NET WebAPI, asp. netwebapi
For. NET distributed application development, many technologies and frameworks are available for us, such as webservice,. net remoting, MSMQ, and WCF. Many of these technologies are not unfamiliar and have no in-depth understanding at the moment. However, I have certainly heard that each technology has its own advantages and applicability. There is no absolute quality, but only a relatively appropriate degree. Unfortunately, today we are not talking about these technologies. Today we are mainly talking about ASP. NET WebAPI.
For ASP. the advantages and features of the NET WebAPI will not be discussed here. You will naturally choose what you need to use, and you will not need to waste some space to explain this. This blog post mainly explains ASP.. NET WebAPI.
1. HTTP overview of WebAPI:
I will not introduce the relevant content of the HTTP protocol here. I have already introduced it in my previous blog post. Now I will provide the address, because too many repeat statements will be a waste of time, I just want to read this blog post and I already know about the HTTP protocol and WebAPI. Blog address:
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. In versions earlier than. NET4.5, process the core HTTP object:
(1) On the client: System. Net. HttpWebRequest is used to initialize HTTP requests and process related responses; System. Net. HttpWebResponse is used to process HTTP Response Headers and Data Reading searches.
(2) on the server side: the System. Web. HttpContext, System. Web. HttpRequest, System. Web. HttpResponse class is used in ASP. NET context, representing a single request and response. The System. Net. HttpListenerContext class provides access to HTTP requests and response objects.
2. In. NET4.5, process the core HTTP object:
(1). Use the same class on the client and server. (HttpRequestMessage and HttpResponseMessage objects do not contain context messages, so they can be shared between the server and the client .)
(2). Because TAP (asynchronous task model) is introduced in. NET4.5, in the new HTTP model, async and awit can be used to implement asynchronous programming. (Asynchronous programming can be implemented in a simple and efficient manner)
When we use the old and new HTTP programming models, it is easy to find that in the new HTTP model, the programming difficulty and the simplification of code writing, the execution efficiency is high. In the development of Web projects, we need to understand HTTP knowledge and ASP. the principle of net http processing is not described here. There are also many articles on the Internet for reading and understanding.
For ASP. NET, our programs and servers request access to server interfaces. After the server obtains the HTTP request, it returns the processing result and the local server obtains the returned result. This request-response mode forms a session. For the development of public platforms for many new learning. NET people are somewhat tall (of course this is relatively speaking), and people who have developed such programs in real time many times (developers who call third-party interfaces) it may not be clear to know the principle of this. I think the main core part of the development of such a third-party platform is the processing of the HTTP protocol, after three steps are taken to create a request, obtain a response message, and parse a message, the returned message content is generally json or xml. After obtaining the response message, the message content is deserialized, obtain the entity information of the message and further process it in the program.
In WeAPI, the generation, resolution, and format of messages can be dynamically created and negotiated. Next we will learn more about the core objects used to implement this process.
2. WebAPI HTTP message parsing:
The HTTP protocol is used to exchange requests and response messages between the client and the server. Therefore, the core of HTTP is the message, as long as we know that a message is divided into "Message Header" and "message content", the subjects of our next introduction to the new HTTP programming model are "Message Header" and "message content ".
In the namespace System. Net. Http, there are two core objects: HttpRequestMessage and HttpResponseMessage. The structure of the two objects is as follows:
NameDescriptionVersionGet or set the HTTP message versionContentObtains or sets the content of an HTTP message.MethodHTTP method used to obtain or set HTTP Request InformationRequestUriGet or set the HTTP request UriHeadersObtains the set of HTTP request headers.PropertiesObtains the attribute set of an HTTP request.ToStringReturns the string representing the current object.
This object is mainly used to indicate HTTP request messages. Most of these attributes and methods of this object should not be unfamiliar, because an HTTP message mainly contains the header, message content, and so on. Here we mainly introduce a property Properties, this attribute does not belong to any standard HTTP message. It is not retained during message transmission.
(2). Properties property parsing:
[__DynamicallyInvokable]public IDictionary<string, object> Properties{ [__DynamicallyInvokable] get { if (this.properties == null) { this.properties = new Dictionary<string, object>(); } return this.properties; }}
The code above clearly shows that this attribute only has one read-only attribute and returns an IDictionary <string, object>. When a message is processed locally on the server or client, this attribute is used to save additional message information. This attribute is only a common container that saves the local message attributes. (Client Authentication related to the connection to receive messages; matching the message with the configured route to obtain the route data)
2. HttpResponseMessage object parsing:
(1). Overview of main attributes and methods of HttpRequestMessage:
| Name |
Description |
| EnsureSuccessStatusCode |
If the IsSuccessStatusCode attribute of the HTTP response is false, an exception is thrown. |
| StatusCode |
Get or set the HTTP response status code |
| ReasonPhrase |
Get or set the reason phrase that the server and status code normally send together |
| RequestMessage |
Obtain or set the request message that causes this Response Message |
| IsSuccessStatusCode |
Gets a value indicating whether the HTTP response is successful. |
Some attributes of this object are not listed, because the HttpRequestMessage object has been introduced, such as Version, Content, Headers, etc. This object is mainly used to indicate HTTP response messages. This section describes the StatusCode attributes.
(2). StatusCode attributes:
[__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; }}
The StatusCode attribute is an enumeration attribute that can be read and written. Many people know the concept of Status Code. In HTTP, the status code mainly indicates the result of processing a message request on the server. The status includes 2XX, 3XX, 4XX, 5XX, and so on.
3. HTTP model message header parsing:
In HTTP, additional fields called headers can be used for request, response, and message content, including more information.
(1). header classification:
| Header name |
Description |
HTTP model header container class |
| User-Agent |
Provide extended information for the request, describing the application that generates the request |
HttpRequestHeaders |
| Server |
Provide extended information about the source server software for the response |
HttpResponseHeaders |
| Content-Type |
Defines the media type used by the resource in the request or response payload body. |
HttpContentHeaders |
(2) HttpHeaders abstract class analysis:
| Name |
Description |
| Add |
Add the specified header and its value to the HttpHeaders set. |
| TryAddWithoutValidation |
Returns a value indicating whether the specified header and its value have been added to the HttpHeaders set, without verifying the information provided. |
| Clear |
Removes all headers from the HttpHeaders set. |
| Remove |
Removes the specified header from the HttpHeaders set. |
| GetValues |
Returns the header values of all specified headers stored in the HttpHeaders set. |
| Contains |
If the specified header exists in the HttpHeaders set, return. |
| ToString |
Returns the string representing the current HttpHeaders object. |
HttpHeaders is an abstract class. HttpRequestHeaders, HttpResponseHeaders, and HttpContentHeaders inherit the class. Next, let's take a look at the Add () method:
[__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); }}
The Add () method has two overloaded versions. This method can Add a header to the container. If the header to be added has a standard name, the header value will be verified before it is added. The Add method also verifies whether the header can have multiple values.
4. HTTP message content parsing:
In the HTTP model of. NET4.5, the HTTP message body is represented by the abstract base class HttpContent. Both the HttpResponseMessage and HttpRequestMessage objects contain an HTTP Content attribute.
(1) main attributes and methods of HttpContent:
| Name |
Description |
| ReadAsByteArrayAsync |
Write HTTP content to the byte array asynchronously. |
| SerializeToStreamAsync |
Serialize HTTP content to a stream in asynchronous mode. |
| CopyToAsync |
Write HTTP content to the stream asynchronously. |
| Loadparts bufferasync |
Serialize HTTP content to the memory buffer using asynchronous operations. |
| CreateContentReadStreamAsync |
Write HTTP content to the memory stream asynchronously. |
| TryComputeLength |
Determine whether the HTTP content has a valid byte length. |
| Headers |
Obtain the Content Header according to the definition in RFC 2616. |
(2). parse the CopyToAsync () method:
[__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;}
When using the message content, you must use the HtppContent method or extension method. In HttpContent, The CopyToAsync () method is used to access the original message content in Push mode. The method code shows that this method accepts two parameters: a stream object, one is information about transmission (for example, channel binding). This parameter can be null. This method can write the message content into the stream.
A generic TaskCompletionSource <object> object is created in the implementation code of this method. This object indicates the producer who is not bound to the delegated Task <TResult>, you can also use the Task attribute to access the user. The SerializeToStreamAsync method serializes the passed Stream object. This method is an Asynchronous Method.
Note the following points: create and use the delegate. in C #, try to use the delegate class provided by. NET. Do not create it by yourself. Another point is the exception handling method in the program. Exception capturing is hierarchical and a custom exception handling method TrySetException is called.
(2) ReadAsStreamAsync () method parsing:
When obtaining the original message content, besides calling the method described above, you can also call the ReadAsStreamAsync () method to access the original message content in PULL mode.
There are two other similar methods in HttpContent: ReadAsStringAsync () and ReadAsByteArrayAsync () provide buffer copies of the message content asynchronously, ReadAsByteArrayAsync () returns the original byte content, ReadAsStringAsync () decodes the content into a string and returns it.
Iii. Analysis of old and new HTTP models in DotNet: 1. Create an http post request instance in versions earlier than NET4.5:
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 (); requ Est. 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 (); // send the request and obtain the response data, and obtain the response var response = request of the HTTP request. getRes Ponse () 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. Create an http post request instance in NET4.5:
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); } } } } }Iv. Summary:
The preceding sections mainly explain how to use this function. some content of the HTTP programming mode in versions earlier than NET4.5 and later, the main difference between the two is. the HTTP programming model earlier than NET4.5 distinguishes the client and server. The objects used by the two are different. Although the implementation principles are similar, the classes used are different .. In Versions later than NET4.5, the use of objects is not divided into clients and servers. The two can be shared.