[ASP.NET Web API]如何Host定义在独立程序集中的Controller
2014-04-11 00:11
495 查看
[ASP.NET Web API]如何Host定义在独立程序集中的Controller
[code] public class FooController : ApiController
{
public string Get()
{
return this.GetType().AssemblyQualifiedName;
}
}
public class BarController : ApiController
{
public string Get()
{
return this.GetType().AssemblyQualifiedName;
}
}
public class BarController : ApiController
{
public string Get()
{
return this.GetType().AssemblyQualifiedName;
}
}
[/code]
[/code]
我们在作为宿主的Hosting程序中利用如下的代码以Self Host模式实现了针对Web API的寄宿。我们针对基地址“http://127.0.0.1:3721”创建了一个HttpSelfHostServer,在开启之前我们注册了一个URL模板为“api/{controller}/{id}”的路由。
[code] [code] class Program
{
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://127.0.0.1:3721");
using (HttpSelfHostServer httpServer = new HttpSelfHostServer(new HttpSelfHostConfiguration(baseAddress)))
{
httpServer.Configuration.Routes.MapHttpRoute(
name : "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults : new{ id = RouteParameter.Optional});
httpServer.OpenAsync().Wait();
Console.Read();
}
}
}
[/code]
[/code]
在启动宿主程序后,我们试图通过浏览器对分别定义在FooController、BarController和BazController中的Action方法Get发起调用,不幸的是我们会得到如图4-4所示的结果。从显示在浏览器中的消息我们很清楚问题的症结所在:根据路由解析得到HttpController名称并不能得到匹配的类型。
[code] <configuration>
<configSections>
<section name="preLoadedAssemblies"
type="Hosting.PreLoadedAssembliesSettings, Hosting"/>
</configSections>
<preLoadedAssemblies>
<add assemblyName ="Foo.dll"/>
<add assemblyName ="Bar.dll"/>
<add assemblyName ="Baz.dll"/>
</preLoadedAssemblies>
</configuration>
[/code]
[/code]
在创建自定义的AssembliesResolver之前我们先得为这段配置定义相应的配置节和配置元素类型。相关的类型(PreLoadedAssembliesSettings、AssemblyElementCollection和AssemblyElement)定义如下所示,由于配置结构比较简单,在这里我们不对它们作详细介绍了。
[code] [code] public class PreLoadedAssembliesSettings: ConfigurationSection
{
[ConfigurationProperty("", IsDefaultCollection = true)]
public AssemblyElementCollection AssemblyNames
{
get{ return (AssemblyElementCollection)this[""];}
}
public static PreLoadedAssembliesSettings GetSection()
{
return ConfigurationManager.GetSection("preLoadedAssemblies")
as PreLoadedAssembliesSettings;
}
}
public class AssemblyElementCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new AssemblyElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
AssemblyElement serviceTypeElement = (AssemblyElement)element;
return serviceTypeElement.AssemblyName;
}
}
public class AssemblyElement : ConfigurationElement
{
[ConfigurationProperty("assemblyName", IsRequired = true)]
public string AssemblyName
{
get{ return (string)this["assemblyName"];}
set{ this["assemblyName"] = value;}
}
}
[/code]
[/code]
由于我们自定义的AssembliesResolver是对现有DefaultAssembliesResolver的扩展(尽管其程序集提供机制仅仅通过一句代码来实现),我们将类型命名为ExtendedDefaultAssembliesResolver。如下面的代码片断所示,ExtendedDefaultAssembliesResolver继承自DefaultAssembliesResolver,在重写的GetAssemblies方法中我们先通过分析上述的配置并主动加载尚未加载的程序集,然后调用基类的同名方法来提供最终的程序集。
[code] [code] public class ExtendedDefaultAssembliesResolver : DefaultAssembliesResolver
{
public override ICollection<Assembly> GetAssemblies()
{
PreLoadedAssembliesSettings settings = PreLoadedAssembliesSettings.GetSection();
if (null != settings)
{
foreach (AssemblyElement element in settings.AssemblyNames)
{
AssemblyName assemblyName = AssemblyName.GetAssemblyName(element.AssemblyName);
if(!AppDomain.CurrentDomain.GetAssemblies().Any(assembly=>AssemblyName.ReferenceMatchesDefinition(assembly.GetName(),assemblyName)))
{
AppDomain.CurrentDomain.Load(assemblyName);
}
}
}
return base.GetAssemblies();
}
}
[/code]
[/code]
我们在作为宿主的Hosting程序中利用如下的代码将一个ExtendedDefaultAssembliesResolver对象注册到当前HttpConfiguration的ServicesContainer上。
[code] [code] class Program
{
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://127.0.0.1:3721");
using (HttpSelfHostServer httpServer = new HttpSelfHostServer(new HttpSelfHostConfiguration(baseAddress)))
{
httpServer.Configuration.Services.Replace(typeof(IAssembliesResolver),new ExtendedDefaultAssembliesResolver());
//其他操作
}
}
}
[/code]
[/code]
重新启动宿主程序后再次在浏览器输入对应的地址来访问分别定义在FooController、BarController和BazController中的Action方法Get,我们会得到如下图所示的输出结果,这正是目标Action方法执行的结果。
相关文章推荐
- [ASP.NET Web API]如何Host定义在独立程序集中的Controller
- ASP.NET Web API的Controller是如何被创建的?
- ASP.NET Web API的HttpController是如何被激活的?
- ASP.NET Web API的Controller是如何被创建的?
- 目标HttpController在ASP.NET Web API中是如何被激活的:目标HttpController的创建
- Asp.net 关于错误提示 类型“XXX1”在未被引用的程序集中定义,必须添加对程序集XXX2的引用
- ASP.NET MVC:看 MVC 源码,学习:如何将 Area 中的 Controller 放到独立的程序集?
- Self Host模式下的ASP. NET Web API是如何进行请求的监听与处理的?
- Self Host模式下的ASP. NET Web API是如何进行请求的监听与处理的?
- 目标HttpController在ASP.NET Web API中是如何被激活的:目标HttpController的选择
- 如何在asp.net程序集中添加winform的选择框(确定,取消)
- asp.net web api的自托管模式HttpSelfHostServer可以以控制台程序或windows服务程序为宿主,不单单依赖于IIS web服务器
- ASP.NET MVC 程序 报错“CS0012: 类型“System.Data.Objects.DataClasses.EntityObject”在未被引用的程序集中定义”的解决办法
- ASP.NET Web API的Controller是如何被创建的?
- OWIN host WebAPI2 使用独立程序集中的Controller
- Self-Host ASP.NET Web API 1
- 白话ASP.NET MVC之三:Controller是如何解析出来的
- asp.net程序中如何自动生成姓名拼音
- ASP.NET C# 如何在程序中控制IIS服务或应用程序池重启?
- host asp.net程序的小型IIS