2012-12-18 27 views
11

Próbuję utworzyć system, który pozwoli mi hostować witrynę "WebAPI" za pośrednictwem aplikacji internetowej lub usługi Windows. W tym celu chcę, aby cała moja logika biznesowa była zawarta w jednej bibliotece klas, tak żebym mógł odwoływać się do tego zarówno w mojej usłudze Windows, jak i mojej usłudze "web" (IIS).Kontroler WebApi przy użyciu biblioteki klas

Mój obecny pomysł polega na użyciu niezależnych opcji zawartych w HttpSelfHostServer. Na koniec strony chciałbym po prostu stworzyć standardową stronę webapi i dodać odniesienie do mojej biblioteki klas.

Co znalazłem to to, że jeśli mam kontroler w tej samej przestrzeni nazw co HttpSelfHostServer, to działa poprawnie, ale jak tylko kontroler znajduje się w zewnętrznej bibliotece klas, serwer nie może już rozstrzygać trasy do mojej kontroli/akcji .

Mój kod:

Okna usługa:

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; 
     } 
    } 
} 

Kontroler:

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"; 
     } 
    } 
} 

Kiedy próbuję przejdź do: "http: // localhost: 8080/api /" I get:

Nie znaleziono zasobu HTTP przy dopasowaniach identyfikator URI żądania "http: // localhost: 8080/api /". Nie znaleziono typu odpowiadającego kontrolerowi o nazwie "Test".

Wszelkie sugestie? Myślę, że powinienem był to zrobić.

+0

Dla jasności - planujesz hostować swój projekt WebAPI zarówno w usługach IIS, jak i samemu hostować w usłudze Windows? –

+0

Tak, zasadniczo, host w IIS lub hostowany, ale co ważniejsze, chcę tylko jedną podstawę kodu, tj. Nie chcę mieć innego kodu dla hostowanych usług IIS z rzeczy hostowanych przez usługę Windows. – TheKingDave

Odpowiedz

0

I w końcu okazało się, jak to musiałem ponownie zorganizować mój kod jako takiego zrobić:

usługi 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; 
     } 
    } 
} 

biblioteka Klasa:

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"; 
     } 
    } 
} 

myślę, że gdzie różne problemy konfiguracyjne z rozwiązaniem usunąłem wszystkie moje referencje i dodałem tylko te wymagane dla każdego projektu.

Dziękuję wszystkim, którzy napisali sugestie.

+0

Twoja odpowiedź jest prawie identyczna z rozwiązaniem w artykule, który podałem w mojej odpowiedzi. Użyłeś tego? – AndyD

+0

Przepraszam, zapomniałem odpowiedzieć tutaj. Przeczytałem już ten artykuł, ale dzięki. – TheKingDave

0

Dla przyszłych czytelników.

Oto (w jedną stronę) sposób korzystania z innego zestawu i używanie usług 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 } 
     ); 
    } 
} 

i

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; 
    } 
} 

i (Global.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()); 
    } 
} 
Powiązane problemy