您的位置:首页 > 编程语言 > ASP

[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方法执行的结果。



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐