Подтвердить что ты не робот

Как настроить Web Api 2 для поиска контроллеров в отдельном проекте? (так же, как я делал в Web Api)

Я использовал для размещения контроллеров в отдельном проекте библиотеки классов в Mvc Web Api. Раньше я добавлял следующую строку в мой веб-проект api global.asax для поиска контроллеров в отдельном проекте:

ControllerBuilder.Current.DefaultNamespaces.Add("MyClassLibraryProject.Controllers");

Мне никогда не приходилось выполнять какую-либо другую конфигурацию, кроме добавления вышеприведенной строки. Это всегда срабатывало для меня.

Однако я не могу использовать вышеуказанный метод, чтобы сделать то же самое в WebApi2. Это просто не работает. Проект WebApi2 по-прежнему пытается найти контроллеры в своей собственной папке диспетчера проектов.

- Предоставление небольшого сводного обновления через 2 месяца (Поскольку я начал щедрость на этом):

Я создал решение WebApiOne, у него есть 2 проекта, первый - проект WebApi, а второй - библиотека классов для контроллеров. Если я добавлю ссылку на проект библиотеки классов контроллеров в проект WebApi, все будет работать так, как ожидалось. то есть, если я перейду к http://mydevdomain.com/api/values, я могу увидеть правильный вывод.

Теперь я создаю второй проект под названием WebApiTwo, у него есть 2 проекта, первый - проект WebApi2, а второй - библиотека классов для контроллеров. Если я добавлю ссылку на проект библиотеки классов контроллеров в проект WebApi2, он не будет работать должным образом. то есть, если я перехожу к http://mydevdomain.com/api/values, я получаю "Тип не найден, который соответствует контроллеру с именем" values".

для первого проекта я вообще не выполняю никаких пользовательских настроек, у меня нет:

ControllerBuilder.Current.DefaultNamespaces.Add("MyClassLibraryProject.Controllers");

в моем global.asax, и я не реализовал какие-либо пользовательские решения, предложенные StrathWeb в двух своих блогах, поскольку я думаю, что он больше не применим; потому что все работает только путем добавления ссылки проекта контроллера на проект WebApi.

Итак, я бы ожидал, что все будут работать одинаково для WebApi2... но это не так. Кто-нибудь действительно пытался сделать это в WebAPi2?

4b9b3361

Ответ 1

Я только что подтвердил, что это работает отлично. Что нужно проверить:

Ссылки: Связан ли ваш основной проект веб-API с внешней библиотекой классов?

Маршрутизация: Установили ли вы какие-либо маршруты, которые могут мешать внешним контроллерам?

Уровень защиты: Являются ли контроллеры во внешней библиотеке public?

Наследование: Выполняют ли контроллеры во внешней библиотеке от ApiController?

Версии: Являются ли оба проекта веб-API и библиотека классов одинаковой версией библиотек веб-API?

Если это поможет, я могу упаковать свое тестовое решение и сделать его доступным для вас. Кроме того, в качестве отправной точки вам не нужно указывать веб-API, чтобы найти контроллеры с линией, добавленной в Global.asax, система автоматически находит контроллеры, если вы ссылаетесь на них.

Ответ 2

Он должен работать так, как есть. Контрольный список

  • Наследовать ApiController
  • Введите имя контроллера с помощью контроллера. Например. ValuesController
  • Убедитесь, что проект проекта WebApi и библиотеки классов ссылаются на те же сборки WebApi
  • Попробуйте использовать маршруты с помощью маршрутизации атрибутов
  • Clean, вручную удалите папки bin и перестройте
  • Удалить папки Temporary ASP.NET Files. Результат поиска контроллера кэша WebApi и MVC
  • Вызов `config.MapHttpAttributeRoutes(); для обеспечения того, чтобы структура учитывала маршруты атрибутов
  • Убедитесь, что метод, который вы вызываете, предназначен для обработки правильного HTTP-глагола (если это веб-метод GET, вы можете вызывать через URL-адрес браузера, если это POST, вам нужно создать веб-запрос)

Этот контроллер:

[RoutePrefix("MyValues")]
public class AbcController : ApiController
{
    [HttpGet]
    [Route("Get")]
    public string Get()
    {
        return "Ok!";
    }
}

соответствует этому URL:

http://localhost/MyValues/Get (обратите внимание, что в маршруте нет /api/, потому что он не указан в RoutePrefix.


Кэширование поиска контроллера: Это контроллер контроллера по умолчанию. Вы увидите в исходном коде, что он кэширует результат поиска.

/// <summary>
/// Returns a list of controllers available for the application.
/// </summary>
/// <returns>An <see cref="ICollection{Type}" /> of controllers.</returns>
public override ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver)
{
    HttpControllerTypeCacheSerializer serializer = new HttpControllerTypeCacheSerializer();

    // First, try reading from the cache on disk
    List<Type> matchingTypes = ReadTypesFromCache(TypeCacheName, IsControllerTypePredicate, serializer);
    if (matchingTypes != null)
    {
        return matchingTypes;
    }
...
}

Ответ 3

Выполнялся в том же сценарии, и @justmara установил меня по правильному пути. Здесь, как выполнить силовую нагрузку зависимых сборок от @justmara, ответьте:

1) Переопределить класс DefaultAssembliesResolver

public class MyNewAssembliesResolver : DefaultAssembliesResolver
{
    public virtual ICollection<Assembly> GetAssemblies()
    {

        ICollection<Assembly> baseAssemblies = base.GetAssemblies();
        List<Assembly> assemblies = new List<Assembly>(baseAssemblies);
        var controllersAssembly = Assembly.LoadFrom(@"Path_to_Controller_DLL");
        baseAssemblies.Add(controllersAssembly);
        return baseAssemblies;

    }
}

2) В разделе конфигурации замените значение по умолчанию новой реализацией

config.Services.Replace(typeof(IAssembliesResolver), new MyNewAssembliesResolver());

Я объединил этот синтаксис вместе с помощью указателей из этого блога:

http://www.strathweb.com/2013/08/customizing-controller-discovery-in-asp-net-web-api/

Как уже говорили другие, вы знаете, если вы столкнулись с этой проблемой, если вы вынуждаете контроллер загружать, напрямую ссылаясь на него. Другим способом является, например, результат CurrentDomain.GetAssemblies() и посмотреть, находится ли ваша сборка в списке.

Кроме того: если вы являетесь владельцем собственного хостинга с использованием компонентов OWIN, вы будете сталкиваться с этим. При тестировании следует помнить, что DefaultAssembliesResolver НЕ будет работать до тех пор, пока не будет отправлен первый запрос WebAPI (мне потребовалось некоторое время, чтобы понять это).

Ответ 4

Вы уверены, что ваша ссылка на сборку была загружена ПЕРЕД вызовом службы IAssembliesResolver? Попробуйте вставить какой-нибудь фиктивный код в ваше приложение, что-то вроде

var a = new MyClassLibraryProject.Controllers.MyClass();

в режиме настройки (но не забывайте, что компилятор может "оптимизировать" этот код и полностью удалить его, если "а" никогда не используется). У меня была аналогичная проблема с порядком загрузки сборки. Завершены с зависимыми от нагрузки сбоями при запуске.

Ответ 5

Вам нужно сообщить webapi/mvc, чтобы загрузить вашу сборку. Вы делаете это с разделом компиляции/сборки в вашем web.config.

<compilation debug="true" targetFramework="4.5.2">
  <assemblies>
    <add assembly="XYZ.SomeAssembly" />
  </assemblies>
</compilation>

Просто. Вы можете сделать это с кодом, как предложил @user1821052, но эта версия web.config будет иметь тот же эффект.

Ответ 6

Помимо уже сказанного:

Убедитесь, что у вас нет двух контроллеров с одинаковым именем в разных пространствах имен.

Просто был случай, когда один контроллер (foo.UserApiController) должен быть частично перенесен в новое пространство имен (bar.UserApiController) и URI. Старый контроллер был сопоставлен по соглашению с /userapi, новый был маршрутизирован атрибутом через RoutePrefix["api/users"]. Новый контроллер не работал, пока я не переименовал его в bar.UserFooApiController.

Ответ 7

При использовании AttributeRouting легко забыть украшать ваши методы с помощью атрибута Route, особенно если вы используете атрибут RoutePrefix в классе контроллера. Кажется, что ваша сборка контроллера не была захвачена конвейером веб-api.

Ответ 8

Если ваша библиотека классов построена с помощью EF, то убедитесь, что у вас есть строка соединения, указанная в App.config для проекта библиотеки классов, И в Web.config для вашего веб-API MVC.