Ответ 1
Взгляните на эту статью http://www.strathweb.com/2012/06/using-controllers-from-an-external-assembly-in-asp-net-web-api/
В нем описывается, как загружать в дополнительные сборки с контроллерами в них.
Я пытаюсь создать систему, которая позволит мне размещать веб-сайт "WebAPI" либо через веб-приложение, либо через службу Windows. С этой целью я хочу, чтобы вся моя логика buisness содержалась в одной библиотеке классов, чтобы я мог ссылаться на нее как в моей службе Windows, так и в моей службе "Интернет" (IIS).
Моя нынешняя идея заключается в использовании самостоятельных вариантов размещения, включенных в HttpSelfHostServer. Для веб-конца я просто создаю стандартный веб-сайт 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://localhost: 8080/api/" Я получаю:
Не найден ресурс HTTP, который соответствует URI запроса "http://localhost: 8080/api/". Не было найдено ни одного типа, который бы соответствовал контроллеру с именем "Тест".
Какие-либо предложения? Я думаю, что смогу это сделать.
Взгляните на эту статью http://www.strathweb.com/2012/06/using-controllers-from-an-external-assembly-in-asp-net-web-api/
В нем описывается, как загружать в дополнительные сборки с контроллерами в них.
Для сценария собственного хостинга предусмотрена пользовательская реализация IAssembliesResolver, как предлагают другие решения, и добавьте необходимые сборки в коллекцию либо с помощью типа в сборке контроллера, либо по его пути к файлу.
class AssembliesResolver : DefaultAssembliesResolver
{
public override ICollection<Assembly> GetAssemblies()
{
ICollection<Assembly> baseAssemblies = base.GetAssemblies();
List<Assembly> assemblies = new List<Assembly>(baseAssemblies);
//Load by a type in the assembly
var _serviceAssembly = Assembly.GetAssembly(typeof(CarsController));
//Load from a file
//var _serviceAssembly = Assembly.LoadFrom("abc.dll");
//Check if the assembly is already in the list
//if you are getting the assembly reference by a type in it,
//The assembly will probably be in the list
if (!assemblies.Contains(_serviceAssembly))
assemblies.Add(_serviceAssembly);
return assemblies;
}
Затем в главном методе консоли или в методе OnStart класса сервиса замените службу распознавателя сборок.
var config = new HttpSelfHostConfiguration("http://localhost:3000");
config.Services.Replace(typeof(IAssembliesResolver), new AssembliesResolver());
config.Routes.MapHttpRoute("default", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });
var server = new HttpSelfHostServer(config);
server.OpenAsync().Wait();
В конце концов я узнал, как это сделать, мне пришлось перестроить мой код как таковой:
Служба 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";
}
}
}
Я думаю, что там, где различные проблемы с конфигурацией с решением, поэтому я удалил всю мою ссылку и добавил только те, которые необходимы для каждого проекта.
Спасибо всем, кто разместил предложения.
Для будущих читателей.
Вот (один из способов), как вы используете другую сборку и используете 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;
}
}
и (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());
}
}
У меня похожая проблема, и я делаю следующие действия, и я ее решаю.
TestController ,EmployeeController
т.д.Я также предлагаю использовать атрибуты, такие как [HttpGet], [HttpPost]