通過《ASP.NET Web API的Controller是如何被創建的?》的介紹我們知道默認ASP.NET Web API在Self Host寄宿模式下用於解析程序集的AssembliesResolver是一個DefaultAssembliesResolver對象,它只會提供當前應用程序域已經加載的程序集。如果我們將HttpController定義在非寄宿程序所在的程序集中(實際上在采用Self Host寄宿模式下,我們基本上都會選擇在獨立的項目定義HttpController類型),即使我們將它們部屬在宿主程序運行的目錄中,宿主程序啟動的時候也不會主動去加載這些程序集。由於當前應用程序域中並不曾加載這些程序集,HttpController類型解析將會失敗,HttpController的激活自然就無法實現。[本文已經同步到《How ASP.NET Web API Works?》]
我們可以通過一個簡單的實例來證實這個問題。我們在一個解決方案中定義了如右圖所示的4個項目,其中Foo、Bar和Baz為類庫項目,相應的HttpController類型就定義在這3個項目之中。Hosting是一個作為宿主的控制台程序,它具有對上述3個項目的引用。我們分別在項目Foo、Bar和Baz中定義了三個繼承自ApiController的HttpController類型FooController、BarController和BazController。如下面的代碼片斷所示,我們在這3個HttpController類型中定義了唯一的Action方法Get並讓它返回當前HttpController類型的AssemblyQualifiedName。
1: public class FooController : ApiController
2: {
3: public string Get()
4: {
5: return this.GetType().AssemblyQualifiedName;
6: }
7: }
8:
9: public class BarController : ApiController
10: {
11: public string Get()
12: {
13: return this.GetType().AssemblyQualifiedName;
14: }
15: }
16:
17: public class BarController : ApiController
18: {
19: public string Get()
20: {
21: return this.GetType().AssemblyQualifiedName;
22: }
23: }
我們在作為宿主的Hosting程序中利用如下的代碼以Self Host模式實現了針對Web API的寄宿。我們針對基地址“http://127.0.0.1:3721”創建了一個HttpSelfHostServer,在開啟之前我們注冊了一個URL模板為“api/{controller}/{id}”的路由。
1: class Program
2: {
3: static void Main(string[] args)
4: {
5: Uri baseAddress = new Uri("http://127.0.0.1:3721");
6: using (HttpSelfHostServer httpServer = new HttpSelfHostServer(new HttpSelfHostConfiguration(baseAddress)))
7: {
8: httpServer.Configuration.Routes.MapHttpRoute(
9: name : "DefaultApi",
10: routeTemplate : "api/{controller}/{id}",
11: defaults : new { id = RouteParameter.Optional });
12:
13: httpServer.OpenAsync().Wait();
14: Console.Read();
15: }
16: }
17: }