我们在开发完Asp.Net WebAPI程序后,可以使用WebHost寄宿方式或者SelfHost寄宿方式来部署Asp.Net WebAPI。所谓WebHost寄宿就是通过Asp.Net来实现;所谓SelfHost就是可以通过控制台、WinForm、WPF等方式寄宿。下面我们通过简单的例子来看看WebHost方式和SelfHost方式。
该Demo中包含一个类库项目、一个控制台项目以及一个空的WebForm项目。其中类库项目有一个继承自ApiController的名为HomeController的类;控制台项目实现SelfHost;WebForm项目实现WebHost:
WebAPI代码:
public class HomeController : ApiController { public string Get(string fromStr) { return $"The request is from {fromStr}"; } }
WebHost寄宿方式:
WebHost项目的Global文件代码:
public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { GlobalConfiguration.Configuration.Routes.MapHttpRoute(name: "default", routeTemplate: "api/{controller}/{fromStr}"); } }
启动运行WebHost项目,浏览器输入地址:34827/api/home/webhost:
SelfHost寄宿方式:
SelfHost项目中的Program文件代码:
static void Main(string[] args) { Assembly.Load("WebAPI,Version=1.0.0.1,Culture=neutral,PublicKeyToken=null"); HttpSelfHostConfiguration configuration = new HttpSelfHostConfiguration(":34827/"); using (HttpSelfHostServer server = new HttpSelfHostServer(configuration)) { server.Configuration.Routes.MapHttpRoute(name: "default", routeTemplate: "api/{controller}/{fromStr}"); server.OpenAsync(); Console.Read(); } }
启动运行SelfHost项目,浏览器输入地址:34827/api/home/from_selfhost:
从上面的例子可以看到Asp.Net WebAPI可以有多重寄宿方式,而Asp.Net WebAPI可以实现多种寄宿方式的原因在于:Asp.Net WebAPI有一个独立于寄宿环境的抽象管道,这个抽象管道是Asp.Net WebAPI的消息处理管道。
下面正式进入今天的主题:Asp.Net WebAPI消息处理管道。Asp.Net WebAPI的消息处理管道是一组HttpMessageHandler的有序组合。在这个消息处理管道中,除了最后一个HttpMessageHandler外,其他的都是由DelegatingHandler这个类型组成的委托链,最后一个HttpMessageHandler是最终处理请求(查找Controller、执行Action)的地方。下面我们通过翻看源码来看看组成消息处理管道的这个有序组合都是哪些类型:
在了解完组成Asp.NetWebAPI消息处理管道的类型后,我们通过一个例子来看看是怎么组成的。我们改一下前面的例子,在WebAPI项目中添加两个自定义的HttpMessageHandler和自定义的HttpServer作为“龙头”:
public class MyHttpMessageHanlder1 : DelegatingHandler { } public class MyHttpMessageHanlder2 : DelegatingHandler { } public class MyHttpServer:HttpServer { public MyHttpServer(HttpConfiguration configuration):base(configuration) { } public new void Initialize() { base.Initialize(); } }
修改HomeController的代码:
public class HomeController : ApiController { public Tuple<IEnumerable<string>, IEnumerable<string>> Get(string fromStr) { HttpConfiguration configuration = new HttpConfiguration(); configuration.MessageHandlers.Add(new MyHttpMessageHanlder1()); configuration.MessageHandlers.Add(new MyHttpMessageHanlder1()); MyHttpServer server = new MyHttpServer(configuration); IEnumerable<string> handler1 = GetHandlers(server).ToArray(); server.Initialize(); IEnumerable<string> handler2 = GetHandlers(server).ToArray(); return new Tuple<IEnumerable<string>, IEnumerable<string>>(handler1, handler2); } private IEnumerable<string> GetHandlers(DelegatingHandler handler) { yield return handler.GetType().Name; while (handler.InnerHandler != null) { yield return handler.InnerHandler.GetType().Name; handler = handler.InnerHandler as DelegatingHandler; if (handler == null) break; } } }
运行程序后输入地址:34827/api/home/from: