Я создаю REST-сервер с собственным хостом (используя Owin):
string baseUri = string.Concat("http://+:58452/MyServer");
myserver = WebApp.Start<Startup>(baseUri);
Console.WriteLine("MyServer is listening at " + baseUri);
...
Я создаю статический контроллер, чтобы убедиться, что он работает нормально с моими настройками:
public class SampleController : ApiController
{
public SampleController() { }
[HttpGet]
[Route("api/Sample/Test")]
[Route("api/Sample/Test/{data}")]
[ActionName("Test")]
public string GetTest(string data)
{
return Test(data);
}
[HttpPost]
[Route("api/Sample/Test")]
public string Test([FromBody] string data)
{
return string.Concat("Test - Received ", data);
}
...
Мой класс запуска выглядит так:
public class Startup
{
// This method is required by Katana:
public void Configuration(IAppBuilder app)
{
var webApiConfiguration = ConfigureWebApi();
// Use the extension method provided by the WebApi.Owin library:
app.UseWebApi(webApiConfiguration);
}
private HttpConfiguration ConfigureWebApi()
{
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
"DefaultApi",
"api/{controller}/{action}/{id}",
new { id = RouteParameter.Optional});
DynControllerSelector custom = new DynControllerSelector(config);
config.Services.Replace(typeof(IHttpControllerSelector), custom);
return config;
}
}
Затем я динамически загружаю другой контроллер, который имеет те же методы и определения, что и статический. Для этого я использую пользовательский селектор контроллера:
public DynControllerSelector(HttpConfiguration configuration) : base(configuration)
{
_Configuration = configuration;
_ControlleDescriptorDict = new ConcurrentDictionary<string, HttpControllerDescriptor>();
}
public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
HttpControllerDescriptor httpControllerDesc = null;
try
{
IDictionary<string, HttpControllerDescriptor> controllers = GetControllerMapping();
//string controllerName = base.GetControllerName(request); // is null for some reason
// Just get the controler in a hack way for now
string controllerName = request.RequestUri.LocalPath.Replace("/MyServer/api/", "");
int idx = controllerName.IndexOf("/");
controllerName = controllerName.Substring(0, idx);
if (!controllers.ContainsKey(controllerName))
{
if (_ControlleDescriptorDict.TryGetValue(controllerName, out httpControllerDesc) == false)
{
lock (_mlock)
{
if (_ControlleDescriptorDict.TryGetValue(controllerName, out httpControllerDesc) == false) // Check that controller has not been created while we were waiting for the lock
{
string assemblyName = string.Concat(controllerName, ".dll");
if (System.IO.File.Exists(assemblyName))
{
Assembly assembly = Assembly.LoadFrom(assemblyName);
var types = assembly.GetTypes();
var matchedTypes = types.Where(i => typeof(IHttpController).IsAssignableFrom(i)).ToList();
var matchedController = matchedTypes.FirstOrDefault(i => i.Name.ToLower() == controllerName.ToLower() + "controller");
if (matchedController == null) throw new Exception(string.Concat("Failed to find controller ", controllerName, "Controller"));
httpControllerDesc = new HttpControllerDescriptor(_Configuration, controllerName, matchedController);
_ControlleDescriptorDict.TryAdd(controllerName, httpControllerDesc);
}
else
{
throw new Exception(string.Concat("Failed to load assembly ", assemblyName));
}
}
}
}
}
else
httpControllerDesc = base.SelectController(request);
. . .
Они должны использовать одинаковые настройки маршрутизации.
Я могу вызвать (HTTP GET) мой статический контроллер, используя атрибут маршрутизации: http://localhost:58452/MyServer/api/Sample/Test/hello2 Это прекрасно работает. Проблема в том, что когда я пытаюсь сделать то же самое на моем динамическом контроллере: http://localhost:58452/MyServer/api/MyDynamic/Test/hello2 Я получаю следующую ошибку: {"Message": "Запрошенный ресурс не поддерживает http-метод" GET "."}
Похоже, что маршрутизация атрибутов не включена для моего динамического контроллера. Если я использую параметры запроса, он работает просто отлично: http://localhost:58452/MyServer/api/MyDynamic/Test?data=hello
Как я могу заставить его работать?
Заранее спасибо за вашу помощь
Ник