Precautions and suggestions for HttpClient of Web APIs (IV) and apihttpclient

Source: Internet
Author: User

Precautions and suggestions for HttpClient of Web APIs (IV) and apihttpclient
Preface

Previously, the host mode for manually implementing Web APIs using SelfHost was not too in-depth, so in this article, we will discuss how to use HttpClient to access resources on Web APIs and pay attention to relevant matters. I hope this article will also benefit you.

Simple parameters from XML or Json Content when the Web API method accepts parameter types such as String, Datetime, and Int, however, by default, these methods do not receive parameters from XML or JSON Body. The result is that the request fails. Next, let's demonstrate it.

We use the Default Web API controller. The method and route registration are as follows:

        [HttpPost]        public string GetString(string message)        {            return message;        }         config.Routes.MapHttpRoute(               name: "DefaultApi",               routeTemplate: "api/{controller}/{action}/{message}",               defaults: new { message = RouteParameter.Optional }         );

Next, we use the client to send a POST request and data to request the Web API and return the data, as shown below:

Var client = new HttpClient (); var postUrl = "http: // localhost: 23133/api/default/GetString"; var task = client. postAsJsonAsync <string> (postUrl, "Hello World "). result; // serialize the parameter to JSON and send it to the Body in the Request.

Theoretically, resources can be accessed through URI through the above routing and Request Method Configuration, but the result will surprise you

It can be learned from the fact that the value of the Message Parameter Hello World has been passed, but the parameter of the method on the resource in the request response is not received at this time and the method is not found when 404 is returned.

The above effect may not be too obvious. We use Ajax to pass the time for the request and return the data. The method is as follows:

        public HttpResponseMessage GetDateTime(DateTime time)        {            return Request.CreateResponse<DateTime>(HttpStatusCode.OK, time);        }

The front-end request is as follows (the routing configuration is skipped ):

       $("#btn").click(function () {            $.ajax({                type: "get",                url: "http://localhost:23133/api/Default/GetDateTime",                dataType: "json",                contentType: "application/json; charset=utf-8",                data: { "time": new Date("2015","09","22") },                cache: false,                success: function (r) {                    console.log(r);                }            });        });

The response information is as follows:

{"Message": "The request is invalid. "," MessageDetail ":" for "WebApplication2.Controllers. the DefaultController method "System. net. http. httpResponseMessage GetDateTime (System. dateTime) "cannot be null type" System. dateTime. The parameter dictionary contains a null item. Optional parameters must be of the reference type, can be null, or declared as optional parameters. "}
The error occurs because simple parameters (such as String, Int, and DateTime) are not parsed during a request and are set to null, therefore, if the passed time is null and the time parameter of the method cannot be null, an error occurs. In this case, we use the [FromBody] feature to solve [note] When the value is passed as a string or number in the foreground, it can be parsed and successfully passed to the parameters of the method, when HttpClient is used for transmission, 404 is displayed.

In view of the above, we can successfully modify the method parameters as follows:

  public HttpResponseMessage GetDateTime([FromBody] DateTime time)
We recommend that you pass simple parameters on the front end and use HttpClient to transfer simple parameters. We recommend that you add the FromBody feature to the parameters to avoid both of them. Supplement

Of course, FromBody corresponds to FromURI. By adding this feature, you can obtain the value of this feature parameter on the URL. The URI is as follows:

    var postUrl = "http://localhost:23133/api/default/GetString?message='xpy0928'";

The requested resource is as follows:

        [HttpPost]        public string GetString([FromUri] string message)        {            return message;        }

In this case, the value of this message is xpy0928.

UrlEncoded form String Parsing

We will certainly pass the form data as a dictionary when operating the form. Here we will demonstrate this situation.

The following is the method that the Web API needs to be requested.

        [HttpPost]        public string GetString(string cnblogs)        {            return cnblogs;        }

Next we use the client to access the above method:

Var formVars = new Dictionary <string, string> (); formVars. add ("cnblogs", "xpy0928"); var content = new FormUrlEncodedContent (formVars); var client = new HttpClient (); var postUrl = "http: // localhost: 23133/api/default/GetString "; var task = client. postAsync (postUrl, content ). result; // The parameter is not serialized.

It can be seen from the above that theoretically it is feasible. We use URI to transmit the form data in dictionary form to request the Web API and obtain the value of the cnblogs key. The results will kill you as follows:

This is because the Web API does not work for the cnblogs parameter value mapped to the cnblogs parameter on the method, and the Web API does not map.

Since simple parameters cannot be received, we try to use objects to obtain the value of this parameter, just as submitting parameters to entities in MVC.

First, a class is provided, and the class contains the cnblogs attribute, as follows:

        public class CnblogsModel        {            public string Cnblogs { get; set; }        }

Modify the methods and parameters as follows:

       [HttpPost]        public string GetString(CnblogsModel model)        {            return model.Cnblogs;        }

The next step is the time to witness the miracle. Awesome, angelabababy, the Emperor is heartless, as follows:

[Note] The key to success is that the fields in the object must match the keys in the POST form. If there are multiple keys, the fields in the object must also match.

The above solution is completely feasible, but it seems a little tricky to do so. To accept the parameters in the form, you have to create and match the object, so you have to think of a better way out, since it is for a form, isn't there a corresponding class in the form for accepting such a dictionary? So, start searching, A FormDataCollection (table data set) is found ). It seems feasible. Let's continue to rewrite its Code as follows:

       [HttpPost]        public string GetString(FormDataCollection collection)        {            return collection.Get("cnblogs");        }

The verification is successful as follows:

 

This is much more feasible than the first solution, but it is a bit confusing for such a collection class, why do we have to use the GetValues () method for a single Get or multiple fields instead of directly obtaining data through indexes?

Do you think that simplicity is feasible? You may be wrong. When we run Web APIs on ASP. NET, we can obtain form data by following the steps below:

            var request = HttpContext.Current.Request;            var formKeys = request.Form.AllKeys;
We recommend that you use HttpContext when obtaining form data. current. request, although it is only available in ASP. but in some complex scenarios, for example, you need to obtain data that is not exposed to requests on Web APIs, at this time, using this method will be irreplaceable, and HttpContext in both ASP. NET, MVC, or Web API. So try to avoid using FormDataCollection, even if it seems easier to use it on the route. Supplement (1)

I would like to express my gratitude to you for your questions. At the beginning, I thought it was quite simple. The result was my face-recognition. After studying the transmission and receipt of complex types of data, if it is a specific type, using FormDataCollection won't work. The solution I can think of is to perform the following operations [expect a better solution ]:

Var p = new Person () {Name = "person", Student = new Student () {StuName = "xpy0928" }}; var client = new HttpClient (); var postUrl = new Uri ("http: // localhost: 23133/api/default/GetString"); var task = client. postAsJsonAsync (postUrl, p ). result; // use the PostAsJsonAsync Method for serialization class

Receive messages on Web APIs as follows:

     [HttpPost]        public string GetString(Person p)        {            return p.Name;        }
The reason why FormDataCollection cannot be used for receiving is that the keys and values of the FormUrlEncodedContent parameter must be of the string type. If the class is not a specific class, directly adding keys and values as strings is feasible, however, this situation does not seem realistic, so we still use PostAsJsonAsync for specific classes. Supplement (2)

Thanks to the reminder from Yuanyuan [YoMe and kennywangjin], the above information must be passed explicitly through routing for parameter transfer to succeed. If it is passed through the body in the Request, no resolution will occur.

Access QueryString

There is an extension method in the namespace System. Net. Http as follows:

            var requestUri = Request.RequestUri.ParseQueryString();            var paramValue = requestUri["param"];

This method is efficient in most scenarios, but if there are many parameters in the URI, You Have To explicitly parse these parameters.

As mentioned above, the ing of related parameters in Web APIs is relatively simple, but in some different situations, you have to do some work manually to handle them, at the same time, we may realize that the Web API does not provide any global context objects, such as Request and Formatters in filtering, all operations are based on Web APIs to provide specific methods. That is, methods are tailored for Web APIs. Therefore, when you see powerful Web APIs, you must also see their weaknesses, in this way, we can better deal with different scenarios.

 

Reference page:

Http://www.yuanjiaocheng.net/webapi/action-method-returntype.html

Http://www.yuanjiaocheng.net/webapi/web-api-reqresq-format.html

Http://www.yuanjiaocheng.net/webapi/media-formatter.html

Http://www.yuanjiaocheng.net/webapi/webapi-filters.html

Http://www.yuanjiaocheng.net/webapi/create-crud-api-1.html

It learning materials

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.