HttpActionDescriptor, ASP.NET Web API and an important object

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

Through the front of the "HttpController activation" introduction we already know ASP.NET Web API described by HttpControllerDescriptor HttpController. For each Action method defined in HttpController through an object of type HttpActionDescriptor to describe the basic method, Action metadata information can be found in the corresponding HttpActionDescriptor object. [this is synchronized How ASP.NET Web API Works? ]

Catalog

HttpActionDescriptor

ReflectedHttpActionDescriptor

ActionNameAttribute

The HTTP method name with the support of the

ActionHttpMethodProvider

HttpActionDescriptor

As in the following code snippets, HttpActionDescriptor is an abstract type. We list some properties of the ActionName attribute member definitions, including representative Action name and Configuration properties of the current HttpConfiguration, it comes from the specified HttpControllerDescriptor object name attribute. The attribute ControllerDescriptor to describe the HttpController HttpControllerDescriptor object, the return type and another attribute ReturnType on behalf of Action method.

   1: public abstract class HttpActionDescriptor
   2: {
   3:     //Other members
   4:     public abstract string                               ActionName { get; }
   5:     public HttpConfiguration                            Configuration { get; set; }
   6:     public HttpControllerDescriptor                     ControllerDescriptor { get; set; }
   7:     public abstract Type                                ReturnType { get; }
   8:     public virtual ConcurrentDictionary<object, object> Properties { get; }
   9:     public virtual Collection<HttpMethod>               SupportedHttpMethods { get; } 
  10:  
  11:     public abstract Collection<HttpParameterDescriptor> GetParameters();   
  12: }

Like the HttpControllerDescriptor types, HttpActionDescriptor also defines a Properties property, its type is ConcurrentDictionary<object, object>, so we can use it to use any object attached to a HttpActionDescriptor object.

By default, each Action method support only one unique HTTP method, but we through some programming skills to make a Action method can support multiple HTTP method at the same time. A list of HTTP method for supporting a Action method could be obtained by the corresponding HttpActionDescriptor SupportedHttpMethods. If a Action only supports HTTP-GET, so for a HTTP-POST request, the Action method will not be selected.

ASP.NET Web API premise can be the target of Action method is able to correctly extract the data from the request and parameters are bound to the corresponding method. The normal execution of the bound depends on some parameters for metadata description parameters, ASP.NET Web API through the HttpParameterDescriptor object to describe the parameters of the Action method, and HttpActionDescriptor set a has the following definition of the GetParameters method is used to obtain a list of HttpParameterDescriptor objects describe all of its parameters.

   1: public abstract class HttpActionDescriptor
   2: {
   3:     //Other members
   4:      public abstract Collection<HttpParameterDescriptor> GetParameters();   
   5: }

The programming method based on the characteristics of ASP.NET Web in a custom API is widely used in Web, ASP.NET API framework itself with the help of some application execution characteristics in the Action method to control the target Action, but because of our framework extension purposes may be custom some attributes to the corresponding Action method. For the convenience of our application to obtain property list on the Action method, HttpActionDescriptor defines the following two GetCustomAttributes< for us; T> method overloading.

   1: public abstract class HttpActionDescriptor
   2: {
   3:     //Other members
   4:     public virtual Collection<T> GetCustomAttributes<T>() where T: class;
   5:     public virtual Collection<T> GetCustomAttributes<T>(bool inherit) where T: class;
   6: }

ReflectedHttpActionDescriptor

HttpActionDescriptor is just an abstract type, use the ASP.NET Web by default API specific HttpActionDescriptor type ReflectedHttpActionDescriptor. As the name implies, ReflectedHttpActionDescriptor through the reflection of the way to obtain the metadata used to describe the target Action method.

   1: public class ReflectedHttpActionDescriptor : HttpActionDescriptor
   2: {
   3:     //Other members
   4:     public ReflectedHttpActionDescriptor(HttpControllerDescriptor controllerDescriptor, MethodInfo methodInfo);
   5:  
   6:     public override Collection<HttpParameterDescriptor> GetParameters();
   7:     public override Collection<T> GetCustomAttributes<T>(bool inherit) where T: class;
   8:     
   9:     public MethodInfo                          MethodInfo { get; set; }
  10:     public override string                     ActionName { get; }
  11:     public override Type                       ReturnType { get; }
  12:     public override Collection<HttpMethod>     SupportedHttpMethods { get; }
  13: }

As in the following code snippets, when building a ReflectedHttpActionDescriptor object in addition to the specified HttpControllerDescriptor object used to describe the HttpController outside, still need to specify the description corresponds to the Action method of MethodInfo object (attribute MethodInfo returns the object), related metadata from the.

The return type of ReflectedHttpActionDescriptor using the specified MethodInfo Action method, and takes it as the value of the ReturnType attribute. If the Action method returns the type is void, the ReturnType property returns Null. By default, said the name Action ActionName property returns the Action method. If we need to specify a different name, can be used to the characteristics of ActionNameAttribute.

ActionNameAttribute

For an effective Action method, the method name as the name of the default Action. How to use URL REST for this architecture style is particularly important, for simplicity, aspects of readability and SEO optimization considerations, often we need careful design of a Action URL. If the Action name as a part of the request URL template name, and Action content is always corresponds with the name Action method, which will enable the design we can not be independent of URL.

In order to solve the name Action and separation method, we can in the Action method using the ActionNameAttribute property for the one we want to specify the name of. ActionNameAttribute is defined as follows, said Name Action attribute name directly specified in the constructor.

   1: [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)]
   2: public sealed class ActionNameAttribute : Attribute
   3: {
   4:     public ActionNameAttribute(string name);
   5:     public string Name { get; }
   6: }

In DemoController, the ActionNameAttribute application in the Action method on the Xxx Action name is set to the"Yyy".

   1: public class DemoController: ApiController
   2: {     
  3:     [ActionName("Yyy")]
   4:     public void Xxx();
   5: }

The HTTP method name with the support of the

The Action method defined in a HttpController default only support a unique HTTP method and HTTP method, the name of this support is determined by the Action method. Specifically, if the Action method name with the following prefixes (case insensitive), then the corresponding HTTP method will default to be supported. For example, if the Action method is named "GetXxx", then the default HTTP-GET support. If the Action method name does not have such prefix, so the default HTTP-POST.

In order to let the readers to "Action method name decided to support the HTTP method" the default HTTP method selection strategy has a more profound understanding of, we do a simple example. We define the following an inherited from the ApiController DemoController, which has 8 members of a legal Action method, except the last one, Other method, Action method name the other 7 are in the corresponding HTTP method name as a prefix.

   1: public class DemoController : ApiController
   2: {
   3:     public void GetXxx() {}
   4:     public void PostXxx() {}
   5:     public void PutXxx() {}
   6:     public void DeleteXxx() {}
   7:     public void HeadXxx() {}
   8:     public void OptionsXxx() {}
   9:     public void PatchXxx() {}
  10:     public void Other() {}
  11: }

We define the following a HomeController on an empty ASP.NET in MVC application. In Index the default Action method, we create a corresponding ReflectedHttpActionDescriptor objects are defined in the 8 DemoController methods. The HTTP method Action method corresponding to 8 ReflectedHttpActionDescriptor the name of the object and the support of the name list is converted into a Dictionary<string, string[]> object appear in the default View.

   1: public class HomeController : Controller
   2: {
   3:     public ActionResult Index()
   4:     {
   5:         HttpControllerDescriptor controllerDescriptor = new HttpControllerDescriptor(new HttpConfiguration(), "demo", typeof(DemoController));
   6:         Dictionary<string, string[]> supportedHttpMethods = new Dictionary<string, string[]>();
   7:         foreach (MethodInfo method in typeof(DemoController).GetMethods())
   8:         {
   9:             if (method.DeclaringType == typeof(DemoController))
  10:             {
  11:                 ReflectedHttpActionDescriptor actionDescritor = new ReflectedHttpActionDescriptor(controllerDescriptor, method);
  12:                 supportedHttpMethods.Add(method.Name, actionDescritor.SupportedHttpMethods.Select(httpMethod=>httpMethod.Method).ToArray());
  13:             }
  14:         }
  15:         return View(supportedHttpMethods);
  16:     }
  17: }

The following is to define the Action method Index corresponding to View, which is a IDictionary<string, string[]> object as a strongly typed View Model. In the View, we will list the HTTP method name Action method and support in the form of the show.

   1: @model IDictionary<string, string[]>
   2: <html>
   3: <head>
   4:     <title>The HTTP method Action method name and support</title>
   5: </head>
   6: <body>
   7:     <table>
   8:         <thead>
   9:             <tr>
  10:                 <th>The Action method name</th>
  11:                 <th>Support the HTTP method</th>
  12:             </tr>
  13:         </thead>
  14:         <tbody>
  15:             @foreach (var item in Model)
  16:             {
  17:                 <tr>
  18:                     <td rowspan="@item.Value.Length">@item.Key</td>
  19:                     <td>@item.Value[0]</td>
  20:                 </tr>
  21:                 for (int i = 1; i < item.Value.Length; i++)
  22:                 { 
  23:                     <tr><td>@item.Value[i]</td></tr>
  24:                 }
  25:             }
  26:         </tbody>
  27:     </table>
  28: </body>
  29: </html>

image

Direct run this program will get the output results as shown on the right in the browser. We can see clearly that corresponds to the HTTP method to support the definition of the 7 Action methods in the front of the DemoController prefix to the name of the method used, and finally a method Action Other is using the default HTTP-POST HTTP method as the only supported.

The Action method name to determine its HTTP method to support strategy although to some extent is our programming easy, but in many cases and our expectation is not consistent. For example, we define a RetrieveContacts Action method to obtain the corresponding contact, it supports HTTP method should be HTTP-GET, but according to the HTTP method of practical support HTTP-POST.

In addition, the Action method by default a support only one unique HTTP method, but in many cases we hope that a Action can support multiple HTTP method. For example, we define a UpdateContact Action method, it is to add support for new contacts also support existing contacts to modify, so we hope that it will also support the two HTTP methods of HTTP-POST and HTTP-PUT. These two cases can be solved through the application of ActionHttpMethodProvider in Action method and the corresponding characteristics of the.

ActionHttpMethodProvider

As the name implies, ActionHttpMethodProvider is the corresponding Action used to provide HTTP support, all of the ActionHttpMethodProvider implementation of the System.Web.Http.Controllers.IActionHttpMethodProvider interface. As in the following code snippets, IActionHttpMethodProvider interface defines a unique read-only HttpMethods returns the HTTP collection.

   1: public interface IActionHttpMethodProvider
   2: {
   3:     Collection<HttpMethod> HttpMethods { get; }
   4: }

ActionHttpMethodProvider in a characteristic way applied to the corresponding Action method. ASP.NET Web API defines two kinds of realization of the characteristics of IActionHttpMethodProvider interface for us, one has the following definition of AcceptVerbsAttribute. When we apply the properties of AcceptVerbsAttribute to an Action method, HTTP method can be specified directly, it supports in the constructor in a string name ("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH", the specified the HTTP method names are not case sensitive).

   1: [AttributeUsage(AttributeTargets.Method, AllowMultiple=true, Inherited=true)]
   2: public sealed class AcceptVerbsAttribute : Attribute, IActionHttpMethodProvider, ...
   3: {
   4:     //Other members
   5:     public AcceptVerbsAttribute(params string[] methods);
   6:     public Collection<HttpMethod> HttpMethods { get; }
   7: }

In the following code snippet, we apply the properties of AcceptVerbsAttribute to Action in Update, which can support HTTP-PUT and HTTP-POST two HTTP for simultaneous requests.

   1: public class ContactController : ApiController
   2: {
   3:     //Other members
   4:     [AcceptVerbsAttribute("PUT","POST")] 
   5:     public void Update(Contact contact)
   6:     { 
   7:         //Omit implementation
   8:     }
   9: }

If you are using the AcceptVerbsAttribute characteristic, HTTP method we can with the string specifies that the target Action method support, in order to avoid name specified error HTTP, ASP.NET Web API defines the ActionHttpMethodProvider characteristics of another type for us, which has the following definition of HttpVerbAttribute.

   1: public abstract class HttpVerbAttribute : Attribute, IActionHttpMethodProvider, ...
   2: {
   3:     //Other members
   4:     protected HttpVerbAttribute(HttpMethod httpMethod);
   5:     public Collection<HttpMethod> HttpMethods { get; }
   6: }

By the definition of HttpVerbAttribute we can see that it is an abstract type, according to the 7 kinds of commonly used HTTP method we introduced above, ASP.NET Web API inherited HttpVerbAttribute defines the characteristics corresponding to the type of. The specific characteristics of certain HTTP types are defined in the System.Web.Http namespace, they are:

Above we through the application of AcceptVerbsAttribute to implement support for target Action for the two HTTP methods for HTTP-POST and HTTP-POST, we can in the following way in the target Action method using HttpPutAttribute and HttpPostAttribute to achieve the same effect.

   1: public class ContactController : ApiController
   2: {
   3:     //Other members
   4:     [HttPut] 
   5:     [HttpPost] 
   6:     public void Update(Contact contact)
   7:     { 
   8:         //Omit implementation
   9:     }
  10: }

Above we achieved through the presentation of the HTTP method by default based on the Action method name support strategy, we follow the HttpGetAttribute and HttpPostAttribute is applied to the 8 Action methods defined in DemoController, the Action method are all provided by HTTP-GET and HTTP-POST request support.

   1: public class DemoController : ApiController
   2: {
   3:     [HttpGet]
   4:     [HttpPost]
   5:     public void GetXxx() {}
   6:  
   7:     [HttpGet]
   8:     [HttpPost]
   9:      public void PostXxx(){}
  10:  
  11:     [HttpGet]
  12:     [HttpPost]
  13:      public void PutXxx(){}
  14:  
  15:     [HttpGet]
  16:     [HttpPost]
  17:     public void DeleteXxx(){}
  18:  
  19:     [HttpGet]
  20:     [HttpPost]
  21:     public void HeadXxx(){}
  22:  
  23:     [HttpGet]
  24:     [HttpPost]
  25:     public void OptionsXxx() {}
  26:  
  27:     [HttpGet]
  28:     [HttpPost]
  29:     public void PatchXxx() {}
  30:  
  31:     [HttpGet]
  32:     [HttpPost]
  33:     public void Other() {}
  34: }

Run this program again after showing the results as shown in the browser. We can clearly see the 8 Action method defined in DemoController are provided on the two kinds of HTTP methods HTTP-GET and HTTP-POST support.

image

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Candice at November 18, 2013 - 3:25 AM