2012-12-18 169 views
11

我正在嘗試創建一個允許我通過Web應用程序或通過Windows服務託管「WebAPI」網站的系統。爲此,我希望所有的buisness邏輯都包含在一個類庫中,以便我可以在Windows服務和我的「web」(IIS)服務中引用它。使用類庫的WebApi控制器

我目前的想法是使用HttpSelfHostServer中包含的自託管選項。對於Web端,我只需創建一個標準的webapi網站,並添加一些對我的類庫的引用。

什麼我發現是,如果我在相同的命名空間HttpSelfHostServer它工作正常,但只要控制器是一個外部類庫中的服務器不再能夠解決我的控制路徑/動作控制器。

我的代碼:

Windows服務:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Diagnostics; 
using System.Linq; 
using System.ServiceProcess; 
using System.Text; 
using System.Reflection; 
using System.IO; 

using System.Web.Http.SelfHost; 
using System.Web.Http; 
using System.Web.Http.Dispatcher; 

using WebApiClasses; 
using WebApiClasses.Controllers; 

namespace WebAPISelfHost 
{ 
    public partial class Service1 : ServiceBase 
    { 
     private HttpSelfHostServer _server; 
     private readonly HttpSelfHostConfiguration _config; 
     public const string ServiceAddress = "http://localhost:8080"; 

     public Service1() 
     { 
      InitializeComponent(); 

      _config = new HttpSelfHostConfiguration(ServiceAddress); 

      //AssembliesResolver assemblyResolver = new AssembliesResolver(); 
      //_config.Services.Replace(typeof(IAssembliesResolver), assemblyResolver); 

      _config.Routes.MapHttpRoute("DefaultApi", 
       "api/{controller}/{id}", 
       new { id = RouteParameter.Optional }); 

     } 

     protected override void OnStart(string[] args) 
     { 
      _server = new HttpSelfHostServer(_config); 
      _server.OpenAsync(); 
     } 




     protected override void OnStop() 
     { 
      _server.CloseAsync().Wait(); 
      _server.Dispose(); 
     } 
    } 

    //public class TestController : ApiController 
    //{ 
    // public string Get() 
    // { 
    //  return "This is an internal test message."; 
    // } 
    //} 

    class AssembliesResolver : DefaultAssembliesResolver 
    { 
     public override ICollection<Assembly> GetAssemblies() 
     { 
      ICollection<Assembly> baseAssemblies = base.GetAssemblies(); 
      List<Assembly> assemblies = new List<Assembly>(baseAssemblies); 

      // Add whatever additional assemblies you wish 

      var controllersAssembly = Assembly.LoadFrom(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\WebApiClasses.dll"); 
      baseAssemblies.Add(controllersAssembly); 
      return assemblies; 
     } 
    } 
} 

控制器:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

using System.Web.Http; 

namespace WebApiClasses.Controllers 
{ 
    public class TestController : ApiController 
    { 
     public string Get() 
     { 
      return "hello from class library"; 
     } 
    } 
} 

當我嘗試導航到: 「HTTP://本地主機:8080/API /」 我得到:

沒有找到HTTP資源匹配請求URI'http:// localhost:8080/api /'。 未找到與名爲「Test」的控制器匹配的類型。

有什麼建議嗎?我想我應該可以做到這一點。

+0

只要是明確的 - 你打算同時託管在IIS和Windows服務自託管你的WebAPI項目? –

+0

是基本,主機在IIS或自託管的,但更重要的是我只想要一個代碼庫,即我不想要有不同的代碼爲IIS託管的東西從窗口服務承載的東西。 – TheKingDave

回答

0

我終於找到了如何做到這一點,我不得不重新安排我的代碼,例如:

Windows服務:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Diagnostics; 
using System.Linq; 
using System.ServiceProcess; 
using System.Text; 
using System.Reflection; 
using System.IO; 

using System.Threading.Tasks; 
using System.Web.Http; 
using System.Web.Http.Dispatcher; 
using System.Web.Http.SelfHost; 

namespace WebAPISelfHost 
{ 
    public partial class Service1 : ServiceBase 
    { 
     static HttpSelfHostServer CreateHost(string address) 
     { 
      // Create normal config 
      HttpSelfHostConfiguration config = new HttpSelfHostConfiguration(address); 

      // Set our own assembly resolver where we add the assemblies we need 
      AssembliesResolver assemblyResolver = new AssembliesResolver(); 
      config.Services.Replace(typeof(IAssembliesResolver), assemblyResolver); 

      // Add a route 
      config.Routes.MapHttpRoute(
       name: "default", 
       routeTemplate: "api/{controller}/{id}", 
       defaults: new { controller = "Home", id = RouteParameter.Optional }); 

      HttpSelfHostServer server = new HttpSelfHostServer(config); 
      server.OpenAsync().Wait(); 

      return server; 
     } 

     public Service1() 
     { 
      InitializeComponent(); 

     } 

     protected override void OnStart(string[] args) 
     { 
      HttpSelfHostServer server = CreateHost("http://localhost:8080"); 
     } 

     protected override void OnStop() 
     { 
     } 
    } 

    class AssembliesResolver : DefaultAssembliesResolver 
    { 
     public override ICollection<Assembly> GetAssemblies() 
     { 
      ICollection<Assembly> baseAssemblies = base.GetAssemblies(); 
      List<Assembly> assemblies = new List<Assembly>(baseAssemblies); 

      assemblies.Add(Assembly.LoadFrom(@"C:\Users\david.kolosowski\Documents\Visual Studio 2010\Projects\WebAPISelfHost\WebAPISelfHost\bin\Debug\ClassLibrary1.dll")); 

      return assemblies; 
     } 
    } 
} 

類庫:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

using System.Web.Http; 

namespace ClassLibrary1 
{ 
    public class TestController : ApiController 
    { 
     public string Get() 
     { 
      return "hello from class library2"; 
     } 
    } 
} 

我想有在那裏解決了各種配置問題,所以我刪除了所有的參考資料,並只添加了每個項目所需的資源。

感謝所有發佈建議的人。

+0

您的回答與我在答案中鏈接的文章中的解決方案几乎完全相同。你使用它了嗎? – AndyD

+0

很抱歉,在這裏回覆。我已經閱讀過這篇文章,不過謝謝。 – TheKingDave

0

對於未來的讀者。

以下是(單向)如何使用不同的程序集並使用IIS。

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     // Web API configuration and services 
     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      //routeTemplate: "api/{controller}/{id}", 
      routeTemplate: "api/{controller}/{action}/{id}", 
      defaults: new { id = RouteParameter.Optional } 
     ); 
    } 
} 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 
using System.Web; 
using System.Web.Http.Dispatcher; 

public class MyCustomAssemblyResolver : DefaultAssembliesResolver 
{ 
    public override ICollection<Assembly> GetAssemblies() 
    { 
     ICollection<Assembly> baseAssemblies = base.GetAssemblies(); 
     List<Assembly> assemblies = new List<Assembly>(baseAssemblies); 
     Type myType = typeof(MyControllerInAnotherAssembly); 
     var controllersAssembly = Assembly.GetAssembly(myType); 
     baseAssemblies.Add(controllersAssembly); 
     return assemblies; 
    } 
} 

和(全球。ASAX)

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Http; 
using System.Web.Http.Dispatcher; 
using System.Web.Security; 
using System.Web.SessionState; 


public class Global : System.Web.HttpApplication 
{ 
    protected void Application_Start(object sender, EventArgs e) 
    { 
     WebApiConfig.Register(GlobalConfiguration.Configuration);  
     GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver), new MyCustomAssemblyResolver()); 
    } 
}