Все контроллеры веб-API ASP.NET возвращают 404

Я пытаюсь заставить API-контроллер работать в веб-приложении ASP.NET MVC 4. Однако каждый запрос приводит к 404, и я в тупике.:/

У меня есть стандартный маршрут API-контроллера из шаблона проекта, определенного как:

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

Регистрация вызывается в Global.asax:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    // Register API routes
    WebApiConfig.Register(GlobalConfiguration.Configuration);

    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

    RouteConfig.RegisterRoutes(RouteTable.Routes);
}

У меня есть базовый API-контроллер:

namespace Website.Controllers
{
    public class FavoritesController : ApiController
    {       
        // GET api/<controller>
        public IEnumerable<string> Get()
        {
            return new [] { "first", "second" };
        }

        // PUT api/<controller>/5
        public void Put(int id)
        {

        }

        // DELETE api/<controller>/5
        public void Delete(int id)
        {

        }
    }
}

Теперь, когда я просматриваю localhost: 59900/api/Favorites, я ожидаю, что метод Получить будет вызван, но вместо этого я получаю 404 код состояния и следующий ответ:

<Error>
   <Message>
       No HTTP resource was found that matches the request URI 'http://localhost:59900/api/Favorites'.
   </Message>
   <MessageDetail>
      No type was found that matches the controller named 'Favorites'.
   </MessageDetail>
</Error>

Любая помощь будет принята с благодарностью, я немного потеряю рассудок.:) Спасибо!

Ответ 1

Одна вещь, с которой я столкнулся, заключалась в том, что мои конфигурации зарегистрированы в неправильном порядке в моем файле GLobal.asax, например:

Правильный порядок:

AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);

Неверный порядок:

AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
WebApiConfig.Register(GlobalConfiguration.Configuration);

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

Ответ 2

По существу та же проблема, решенная в моем случае, добавив:

<modules runAllManagedModulesForAllRequests="true" />

в

<system.webServer>

</system.webServer>

раздела web.config

Ответ 3

Я работаю над проблемой, подобной этой, и мне понадобилось много времени, чтобы найти проблему. Это не решение для этой конкретной должности, но, надеюсь, добавив это, кто-то сэкономит время, пытаясь найти проблему, когда они ищут, почему они могут получить ошибку 404 для своего контроллера.

В принципе, я неправильно записал "Контроллер" в конце имени моего класса. Просто как это!

Ответ 4

Добавьте следующую строку

GlobalConfiguration.Configure(WebApiConfig.Register);

в Application_Start() в файле Global.ascx.cs.

Ответ 5

Создайте атрибут Route для вашего метода.

Пример

        [Route("api/Get")]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

Вы можете назвать такие http://localhost/api/Get

Ответ 6

Я немного в тупике, не уверен, что это связано с проблемой кэширования вывода HTTP.

В любом случае "внезапно он начал нормально работать".:/Итак, приведенный выше пример работал без меня, добавляя или меняя что-либо.

Угадайте, что код просто должен был сидеть и готовить всю ночь...:)

Спасибо, что помогли, ребята!

Ответ 7

Я собираюсь добавить свое решение здесь, потому что лично я ненавижу тех, которые редактируют web.config, не объясняя, что происходит.

Для меня было установлено, что сопоставления обработчиков по умолчанию заданы в IIS. Чтобы проверить это...

  • Откройте диспетчер IIS
  • Нажмите на корень node вашего сервера (обычно это имя сервера)
  • Откройте "Отображения обработчиков"
  • В разделе Действия в правой панели нажмите "Просмотреть список заказов"

Это порядок обработчиков, обрабатывающих запрос. Если вы похожи на мои, обработчики "ExtensionlessUrlHandler- *" находятся ниже обработчика StaticFile. Ну, это не сработает, потому что обработчик StaticFile имеет подстановочный знак * и вернет 404, прежде чем даже перейти на контроллер без расширения.

Таким образом, переставив это и перемещая "ExtensionlessUrlHandler- *" над обработчиками подстановок TRACE, OPTIONS и StaticFile, сначала будет активирован обработчик Extensionless, и он должен позволить вашим контроллерам на любом веб-сайте, работающем в системе, правильно реагировать.

Примечание: Это в основном то, что происходит, когда вы удаляете и добавляете модули в web.config, но в одном месте, чтобы решить все. И он не требует дополнительного кода!

Ответ 8

Добавьте это в <system.webServer> в свой файл web.config:

<handlers>
    <remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
    <remove name="OPTIONSVerbHandler"/>
    <remove name="TRACEVerbHandler"/>
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler"
        preCondition="integratedMode,runtimeVersionv4.0"/>
</handlers>

Добавление <modules runAllManagedModulesForAllRequests="true" /> также работает, но не рекомендуется из-за проблем с производительностью.

Ответ 9

Убедитесь, что если ваш класс контроллера имеет атрибут [RoutePrefix ( "somepath" )], все методы контроллера также имеют атрибут [Route()]. ​​

Я столкнулся с этой проблемой и некоторое время царапал себе голову.

Ответ 10

Я решил подобную проблему, связав с отладчиком приложение init. Просто запустите веб-сервер (например, обратитесь к localhost), присоединитесь к w3wp и посмотрите, если инициализация приложения закончена правильно. В моем случае было исключение, и контроллеры не были зарегистрированы.

Ответ 11

У меня была такая же проблема 404, и ни одно из вышеперечисленных решений здесь не работало. В моем случае у меня есть суб-приложение со своим собственным web.config, и у меня был явный тег внутри родительского httpModules web.config. В IIS все родительские настройки web.config применяются к под-приложению.

<system.web>    
  <httpModules>
    <clear/>
  </httpModules>
</system.web>

Решение состоит в том, чтобы удалить тег 'clear' и возможно добавить inheritInChildApplications = "false" в родительский web.config. Признак inheritInChildApplications предназначен для того, чтобы IIS не применял настройки конфигурации к под-приложению.

<location path="." inheritInChildApplications="false">
  <system.web>
  ....
  <system.web>
</location>

Ответ 12

У меня была та же проблема, и я узнал, что у меня есть дубликаты имен классов контроллера API в другом проекте и, несмотря на то, что "routePrefix" и имя пространства имен и проектов были разными, но все же они вернулся 404, я изменил имена классов и работал.

Ответ 13

По причинам, которые не ясны для меня, я объявил все свои методы/действия статическими - видимо, если вы это сделаете, это не сработает. Поэтому просто отпустите static off

[AllowAnonymous]
[Route()]
public static HttpResponseMessage Get()
{
    return new HttpResponseMessage(System.Net.HttpStatusCode.OK);
}

Стала: -

[AllowAnonymous]
[Route()]
public HttpResponseMessage Get()
{
    return new HttpResponseMessage(System.Net.HttpStatusCode.OK);
}

Ответ 14

WebApiConfig.Register(GlobalConfiguration.Configuration);

Должен быть первым в событии App_start. Я пробовал его в последней позиции в событии APP_start, но это не сработало.

Ответ 15

Аналогичная проблема с неловко простым решением - убедитесь, что ваши методы API public. Оставляя какой-либо метод, модификатор доступа также возвращает HTTP 404.

Вернет 404:

List<CustomerInvitation> GetInvitations(){

Выполняется как ожидалось:

public List<CustomerInvitation> GetInvitations(){