1. HttpController

  2. establish HttpController

    • IAssembliesResolver
    • IHttpControllerTypeResolver
    • HttpControllerTypeCache
    • IHttpControllerSelector
  3. ServicesContainer

We know from the last section that , In the message pipeline , In the end in HttpControllerDispatcher Of SendAsync Method IHttpController.


Let's see IHttpController

public interface IHttpController
Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken);

IHttpController The design is very similar HttpMessageHandler, It's just that the parameters are determined by HttpRequestMessage Turned into HttpControllerContext

public public class HttpControllerContext
HttpControllerContext(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor)

It can be seen that HttpControllerContext It's actually a package HttpRequestMessage and HttpControllerDescriptor

and HttpControllerDescriptor It's really creating IHttpController The object of

public class HttpControllerDescriptor
public virtual IHttpController CreateController(HttpRequestMessage request)
// Create... With built-in lightweight containers
return this.Configuration.Services.GetHttpControllerActivator().Create(request, this, this.ControllerType);

This section focuses on HttpControllerDescriptor Of CreateController Method

establish HttpController

Talking about creating HttpController front , We need to understand HttpControllerDescriptor How it was created

The whole creation process needs to go through the following steps


First, through IAssembliesResolver Find the assembly that matches

The default implementation is to find assemblies in the current application domain

public class DefaultAssembliesResolver : IAssembliesResolver
public virtual ICollection<Assembly> GetAssemblies()
return (ICollection<Assembly>) ((IEnumerable<Assembly>) AppDomain.CurrentDomain.GetAssemblies()).ToList<Assembly>();

And in the WebHost Next , stay HttpConfiguration In the process of creating WebHostAssembliesResolver

internal sealed class WebHostAssembliesResolver : IAssembliesResolver
ICollection<Assembly> IAssembliesResolver.GetAssemblies()
// All referenced assemblies
return (ICollection<Assembly>) BuildManager.GetReferencedAssemblies().OfType<Assembly>().ToList<Assembly>();


List the available Assemblies after , Will pass IHttpControllerTypeResolver Find all IHttpController

The default implementation is DefaultHttpControllerTypeResolver

public class DefaultHttpControllerTypeResolver : IHttpControllerTypeResolver
public virtual ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver)
foreach (Assembly assembly in (IEnumerable<Assembly>) assembliesResolver.GetAssemblies())
typeArray = assembly.GetTypes();
return typeArray.Where<Type>(x => this.IsControllerTypePredicate(x));
} internal static bool IsControllerType(Type t)
//IsClass IsVisible !IsAbstract IHttpController
if (t != (Type) null && t.IsClass && (t.IsVisible && !t.IsAbstract) && typeof (IHttpController).IsAssignableFrom(t))
return DefaultHttpControllerTypeResolver.HasValidControllerName(t);
return false;


When you find all HttpController after ,IHttpControllerSelector It is used to choose which one can generate HttpControllerDescriptor( When the same Controller The name is in a different namespace , This is WebAPI Will abandon this 2 individual Controller)

The default implementation is DefaultHttpControllerSelector

public class DefaultHttpControllerSelector : IHttpControllerSelector
// On request Select corresponding HttpControllerDescriptor
public virtual HttpControllerDescriptor SelectController(HttpRequestMessage request)
string controllerName = this.GetControllerName(request);
HttpControllerDescriptor controllerDescriptor;
if (GetControllerDescriptor(controllerName, out controllerDescriptor))
return controllerDescriptor;
return null;
} // From routing variables controller In order to get ControllerName
public virtual string GetControllerName(HttpRequestMessage request)
string str;
request.GetRouteData().Values.TryGetValue<string>("controller", out str);
return str;
} public HttpControllerDescriptor GetControllerDescriptor(string controllerName,out HttpControllerDescriptor controllerDescriptor)
// Remove the same name Controller
var keys = ControllerTypeCache.Cache.Where(x=>x.Value.Count == 1).Select(x=>x.Key);
foreach(var key in keys){
return new HttpControllerDescriptor(...);


Here's a little more :

stay DefaultHttpControllerSelector In the code of , We use ControllerTypeCache.Cache

In fact, due to frequent reflection creation Controller,WebAPI Through caching Controller Avoid unnecessary losses .

At the same time DefaultHttpControllerSelector There are also corresponding caching measures in the code ( The code in this article is for easy understanding ).

internal sealed class HttpControllerTypeCache
public HttpControllerTypeCache(HttpConfiguration configuration)
Cache = GetCache(configuration);// This is also pseudo code
internal Dictionary<string, ILookup<string, Type>> Cache {get;}

Through the above process , We know HttpControllerDescriptor How to create , And create HttpControllerDescriptor after , call CreateController You can create public virtual IHttpController CreateController(HttpRequestMessage request)


stay Web API In the message pipeline , There are many interfaces defined , There are many corresponding implementation classes .

WebAPI Customized a set of DI Containers ServicesContainer. And this container is directly attached to HttpConfiguration On

public class HttpConfiguration : IDisposable
public ServicesContainer Services { get; internal set; }
public HttpConfiguration(HttpRouteCollection routes)
this.Services = (ServicesContainer) new DefaultServices(this);

In the default implementation DefaultServices It defines WebAPI The default corresponding implementation

public class DefaultServices : ServicesContainer
private readonly Dictionary<Type, object> _defaultServicesSingle = new Dictionary<Type, object>(); public DefaultServices(HttpConfiguration configuration)
this.SetSingle<IAssembliesResolver>((IAssembliesResolver) new DefaultAssembliesResolver());
this.SetSingle<IHttpControllerActivator>((IHttpControllerActivator) new DefaultHttpControllerActivator());
this.SetSingle<IHttpControllerSelector>((IHttpControllerSelector) new DefaultHttpControllerSelector(configuration));
this.SetSingle<IHttpControllerTypeResolver>((IHttpControllerTypeResolver) new DefaultHttpControllerTypeResolver());
// Set interface implementation
private void SetSingle<T>(T instance) where T : class
this._defaultServicesSingle[typeof (T)] = (object) instance;
// Get the interface implementation
public override object GetService(Type serviceType)
return this._defaultServicesSingle[serviceType];

remarks :

  • The code in this article is not complete WebAPI Code , It's usually simplified by itself .

  • This article uses MarkDown Grammar editor

The starting address :

[Web API] Web API 2 In-depth series (3) Activate HttpController More articles about

  1. ASP.NET Web API - ASP.NET MVC 4 series

           Web API The project is Windows communication interface (Windows Communication Foundation,WCF) The product of the passion of the team and its users , They want to be with HTTP The depth of the integration .WCF ...

  2. How to use Baas Quickly develop small programs on Tencent cloud - series 1: build API &amp; WEB WebSocket The server

    Copyright notice : This paper is written by He Jia   Original article , Reprint please indicate the source :  Link to the original article : source : Tengyun Pavilion  h ...

  3. HTML5 Authoritative guide --Web Storage, Local database , Local cache API,Web Sockets API,Geolocation API( Brief study note 2 )

    1.Web Storage HTML5 except Canvas Beyond elements , There is also a very important function, that is, the local storage of data in the client Web Storage function . Used to cookies Save simple information like user name .   however c ...

  4. What I understand RESTful Web API [Web Standard ]

    REST It's not a standard , It's a software application architecture style . be based on SOAP Of Web Service use RPC framework , if RPC It's an operation oriented architecture style , and REST It's a resource oriented architecture style .REST At present, it is a more popular way to build a new era in the industry ...

  5. restructure Web Api Program (Api Controller and Entity) sequel

    I wrote a summary yesterday < restructure Web Api Program (Api Controller and Entity)>, Exchange some data ...

  6. web api Write api Interface returns

    web api Write api Interface, the default return is to serialize your object with XML returns , So how can we get it back to json Well , Here are two ways : Method 1 :( Change the allocation method ) find Global.asax file , stay Applic ...

  7. Google Maps API Web Services

    original text :Google Maps API Web Services Excerpt from : Goo ...

  8. web api structure api Help document

    1 Summary establish ASP.NET Web Api The template comes with it Help Pages frame . 2 problem 1) Use VS establish Web Api Project time , The template will be Help Pages The framework is automatically integrated into it , bring Web Api project ...

  9. Why? web Developers need to migrate to . NET Core, And use ASP.NET Core MVC structure web and webservice/API

    2018 .NET Developer survey report : .NET Core What kind of state is it , Here we see a lot more .net Developers are still waiting to see , This article gives you a suggestion . This is just my personal opinion , I have every reason to recommend .net Program ...

Random recommendation

  1. knockoutjs introduction

    Knockoutjs introduction ( Conceptual relevance ) about As far as back-end developers are concerned, almost all of us have been exposed to mvc frame .knockoutjs yes MVVM The pattern is a little strange to us .Knockout It's a lightweight UI Class library , through ...

  2. Rendering pipeline overview( Reading notes 1 --- Real-Time rendering)

    1. Rendering pipeline The role of the camera is in a given virtual camera . Three dimensional object . The light source . The coloring equation . Texture, etc ( Rendering ) Two dimensional image 2. pipeline It contains a lot of stage, Its efficiency is improved by the slowest stag ...

  3. devise Small projects ( One )

    Devise From the Warden, and warden It's based on Rack Verify permissions for gem, however , Use devise It doesn't really need anything about warden Knowledge . If you have some other similar functions to maintain and verify permissions before gem Use ...

  4. expr command

    expr The two functions of command :1) arithmetic :2) String operation : 1. arithmetic [tough@localhost ~]$ + + [tough@localhost ~]$ + [tough@localhost ...

  5. Four 、Nginx Load balancing upstream

    user www; worker_processes ; error_log /usr/local/nginx/logs/error.log crit; pid /usr/local/nginx/lo ...

  6. 【 The length and number of the longest descending subsequence 】 poj 1952

    from This problem requires the length and number of the longest descending subsequence , We can add arrays maxlen[size] ...

  7. c# Development wps plug-in unit (3) Deploy

    Last one , We have completed the specific development work , But eventually it has to be deployed to the client machine . therefore , In terms of deployment , I spent some time studying , Now sum up . In the previous , Why do I suggest developers install wps The professional version ? Because of the professional version , It's convenient for us to develop , Ann ...

  8. .Net Core Authority verification and Authorization (AuthorizeFilter、ActionFilterAttribute)

    stay .Net Core Use in AuthorizeFilter perhaps ActionFilterAttribute To verify and authorize login rights One .AuthorizeFilter New authorization class AllowAnonymo ...

  9. [Python] wxPython Basic controls ( turn )

    from : One . Static text control wx.StaticText(parent, id, label, pos= ...

  10. Custom data types typedef

    It's just an alias for a data type . typedef unsigned char AGE; // Character type AGE x; // Equivalent to unsigned char x; typedef int * IPointe ...