Переривчастий виняток mpc asp.net: “Метод публічної дії ABC не вдалося знайти на контролері XYZ.”


92

Я отримую періодичний виняток, який каже, що asp.net mvc не може знайти метод дії. Ось виняток:

Метод публічної дії "Заповнити" не вдалося знайти на контролері "Schoon.Form.Web.Controllers.ChrisController".

Я думаю, що я правильно налаштував маршрутизацію, оскільки ця програма працює більшу частину часу. Ось метод дії контролера.

[ActionName("Fill")]
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post), UserIdFilter, DTOFilter]
public ActionResult Fill(int userId, int subscriberId, DisplayMode? mode)
{
     //…
}

Маршрут:

routes.MapRoute(
        "SchoonForm",
        "Form/Fill/{subscriberId}",
        new { controller = "ChrisController", action = "Fill" },
        new { subscriberId = @"\d+" }
    );

І ось стек:

System.Web.HttpException: Не вдалося знайти метод публічної дії "Заповнення" на контролері "Schoon.Form.Web.Controllers.ChrisController". у System.Web.Mvc.Controller.HandleUnknownAction (String actionName) у C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs: рядок 197 у System.Web.Mvc.Controller.ExecuteCore () в C : \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs: рядок 164 у System.Web.Mvc.ControllerBase.Execute (RequestContext requestContext) в C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebc \ System M ControllerBase.cs: рядок 76 у System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute (RequestContext requestContext) у C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ ControllerBase.cs у System.Web.Mvc.MvcHandler.ProcessRequest (HttpContextBase httpContext) у C:

Ось приклад моїх фільтрів, які всі вони працюють однаково:

public class UserIdFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        const string Key = "userId";

        if (filterContext.ActionParameters.ContainsKey(Key))
        {
            filterContext.ActionParameters[Key] = // get the user id from session or cookie
        }

        base.OnActionExecuting(filterContext);
    }
}

Дякую, Кріс


28
У мене була подібна проблема, на яку, на мою думку, варто звернути увагу, оскільки це був перший результат, який з’явився в Google при пошуку вищезазначеного винятку. У моїй заявці з’явився цей виняток при надсиланні недійсної форми. Це було пов’язано зі сторінкою, яка (повторно) відображалася із викликом RenderAction, а дія, яка була викликана для часткового подання, була позначена атрибутом HttpGet, видалення цього атрибуту вирішило проблему.
s1mm0t

3
Я також помітив таку поведінку - мабуть, найкраще не застосовувати жодні атрибути Http до методів контролера, які повертають PartialViewResults.
Стюарт,

1
@ s1mm0t: правильно. для мого випадку його коментар вирішив проблему
Mazdak Shojaie

@ s1mm0t - негайно надішліть мені свою поштову адресу. Пляшка скотчу вже на шляху до вас цього Різдва !!!!!
Шейн

Ми виявили щось подібне: у певних випадках повернення іншого результату дії замість переспрямування на цю дію спричинило проблему. Ex PostSomething { return HomePageActionMethod() }не PostSomething { return RedirectToAction(nameof(HomePageActionMethod)); }працює там, де працює. (у нашому випадку порушувальна дія у поданні розташована в іншому контролері, і, мабуть, цей контролер не повністю ініціалізований першим способом виклику.
jleach

Відповіді:


62

Ми знайшли відповідь. Ми заглянули в наші веб-журнали. Це показало, що ми отримували деякі дивні http-дії (дієслова / методи), такі як OPTIONS, PROPFIND та HEAD.

Це, здається, є причиною деяких винятків із цих тез. Це пояснює, чому це було періодично.

Ми відтворили проблему за допомогою інструменту curl.exe:

curl.exe -X OPTIONS http://localhost/v2.3.1.0/(S(boztz1aquhzurevtjwllzr45))/Form/Fill/273
curl.exe -X PROPFIND http://localhost/v2.3.1.0/(S(boztz1aquhzurevtjwllzr45))/Form/Fill/273
curl.exe -X HEAD http://localhost/v2.3.1.0/(S(boztz1aquhzurevtjwllzr45))/Form/Fill/273

Виправлення, яке ми використали, було додати розділ авторизації до web.config:

<authorization>
  <deny users="*" verbs="OPTIONS, PROPFIND, HEAD"/>
</authorization>

3
Ми також виявили, що боти іноді сканують ваш сайт - і навіть javascript -, щоб знайти посилання. Потім вони намагаються надіслати запити на ці URI з неправильним HTTP-дієсловом. Наприклад, якщо у вас є виклик jQuery до якоїсь дії - наприклад, / some-action, а цей метод вимагає POST, бот може спробувати надіслати GET, що призведе до появи цієї помилки. Ваші веб-журнали можуть точно допомогти підтвердити, чи це було так. Ми навіть бачимо, як Googlebot робить це.
jakejgordon 01.03.16

У мене така сама помилка лише на сервері Live (IIS 7.5). Розгортання чудово працює як на моїй машині розробки, так і на іншій машині підтримки. додавання цих дієслів та видалення HttpGet не вирішило проблему. Будь-які подальші пропозиції, будь ласка.
bjan

Як альтернативу відмові вхідних запитів HEAD, ви можете надати відповідну відповідь. Дивіться stackoverflow.com/a/3197128/12484
Джон Шнайдер

15

У нас була подібна проблема, але ми виявили, що це відбувалося через те, що користувач публікував повідомлення на контролері після закінчення терміну його входу. Потім система переспрямовувала на екран входу. Після входу він переспрямовував назад на URL-адресу, на яку намагався розмістити користувач, але цього разу він робив замість цього запит GET і, отже, не знаходив дії, позначеної атрибутом [HttpPost].


Моє поточне рішення - це, наскільки це можливо, завжди робити перенаправлення назад до дії Index в кінці дії. Вибачте за пізню відповідь.
Йоганн Стридом,

7

У мене така сама проблема в asp.net mvc. ця помилка - 404 не знайдено. Я вирішую проблему таким чином - помістіть цей код у MyAppControllerBase(MVC)

    protected override void HandleUnknownAction(string actionName)
    {
        this.InvokeHttp404(HttpContext);
    }

    public ActionResult InvokeHttp404(HttpContextBase httpContext)
    {
        IController errorController = ObjectFactory.GetInstance<PagesController>();
        var errorRoute = new RouteData();
        errorRoute.Values.Add("controller", "Pages");
        errorRoute.Values.Add("action", "Http404");
        errorRoute.Values.Add("url", httpContext.Request.Url.OriginalString);
        errorController.Execute(new RequestContext(
             httpContext, errorRoute));

        return new EmptyResult();
    }

6

У нас просто була одна і та ж проблема з нашим додатком, і я зміг відстежити її до проблеми javascript / jquery. У нашому додатку є посилання, визначені за допомогою Html.ActionLink (), які пізніше замінюються на POST за допомогою jquery.

Спочатку ми визначили посилання:

Html.ActionLink("Click Me", "SomeAction", new { id = Model.Id})

Пізніше ми замінюємо дію за замовчуванням за допомогою функції SomePostEventHandler:

 $(document).ready(function() {
      $('#MyLink').click(SomePostEventHandler);
 }

Це вражало нашу дію MVC, яка мала фільтр HttpPost:

 [HttpPost]
 public ActionResult SomeAction(int id)
 {
      //Stuff
 }

Ми виявили, що більшу частину часу це працювало чудово. Однак при деяких повільних завантаженнях сторінок (або дійсно швидких користувачів) користувач натискав посилання до того, як спрацювала подія jquery $ (document) .ready (), що означає, що вони намагалися отримати GET / Controller / SomeAction / XX замість проводка.

Ми не хочемо, щоб користувач отримував цю URL-адресу, тому видалення фільтра для нас не є можливістю. Натомість ми просто підключили подію onclick за посиланням дії (нам довелося трохи змінити SomePostEventHandler (), щоб це працювало):

string clickEvent = "return SomePostEventHandler(this);";

Html.ActionLink("Click Me", "SomeAction", new { id = Model.Id}, new { onclick = clickEvent })

Отже, моральне значення історії, принаймні для нас, полягає в тому, що якщо ви бачите ці помилки, відслідковуйте URL-адресу, яку ви ДУМАЄТЕ, що розміщуєте, і переконайтеся, що є.


Взагалі, ви повинні бути обережними, коли ви публікуєте повідомлення з гіперпосилання html. Гіперпосилання існують для переходу користувача на іншу сторінку (http get), а кнопки html повинні подати форму (http post).
stevie_c

2

У мене теж було це питання.

У моєму випадку це було пов'язано з дієслівними обмеженнями на запитувану дію, де подання було, POSTале часткове подання запитувалося в межах підтримуваного GETта HEADлише. Додавання POSTдієслова до AcceptVerbsAttribute(у MVC 1.0) вирішило проблему.


2

З журналів IIS нашу проблему спричинив Googlebot при спробі POST та GET для дії контролера лише POST.

У цьому випадку я рекомендую обробляти 404, як пропозиція Дмитра.


1

Наразі прийнята відповідь працює належним чином, але це не основний варіант використання функції. Натомість використовуйте функцію, визначену ASP.NET. У моєму випадку я заперечував все, крім GET і POST:

  <system.webServer>
  <security>
      <requestFiltering>
          <verbs allowUnlisted="false">
              <add verb="GET" allowed="true"/>
              <add verb="POST" allowed="true"/>
          </verbs>
      </requestFiltering>
  </security>
 </system.webServer>

З наведеним фрагментом коду MVC правильно поверне 404


0

Не повинно бути

routes.MapRoute(
        "SchoonForm",
        "Form/Fill/{subscriberId}",
        new { controller = "Chris", action = "Fill" },

Крім того, чим займаються ваші фільтри? Чи не можуть вони приховати дію, як ActionMethodSelectorAttribute?


Це помилка редагування. Я намагався захистити невинних.
Кріс Шун,

Вони заповнюють деякі параметри. Наприклад, UserIdFilter є помічником для отримання ідентифікатора користувача із сеансу / cookie / тощо. Він заповнює перший параметр. Я відредагую допис, щоб включити його.
Кріс Шун,

0

У мене схоже питання з завантаженням файлу qq

Коли дія post, /Document/Saveя отримую виняток На контролері "Project.Controllers.DocumentController" не знайдено загальнодоступного методу дії "Зберегти".

Але якщо пост-дія є /Document/Save/ , публікація правильна і працює!

Боже, збережи / ?


0

Моя першопричина була схожа на ту, що згадана в коментарі.

Я був ajaxSubmittingформою після натискання кнопки. Одне з полів форми було типу Date. Однак через різницю у форматах дат між клієнтом та серверною машиною він не виконав метод POST у контролері. Сервер надіслав 302відповідь, а потім надіславGET запит на той самий метод.

Однак дія в контролері була прикрашена HttpPostатрибутом, і, отже, він не зміг знайти метод і надіслав назад a404 відповідь.

Я просто виправив код таким чином, щоб невідповідність у форматах Date не спричиняла помилку, і проблема була виправлена.


0

Видаліть [HttpGet]атрибути, і це буде працювати :)


Поки це "вирішує" помилки, ймовірність того, що ви (або хтось перед вами) спеціально розміщуєте [HttpGet]там ці атрибути, щоб запобігти виклику дій через будь-які інші дієслова
Нік Орландо,

0

Для тих, хто має цю проблему із вставками angularjs, MVC та {{imagepath}} в атрибутах image src, наприклад:

"На контролері не знайдено методу публічної дії '{{imagepath}} previous.png"

Рішення полягає у використанні ng-src замість src.

Сподіваюся, це комусь допомагає :)


майже рік потому я шукав це :) tnx!
Verthosa

0

Подивіться, чи достатньо простого перегляду вказаної URL-адреси, щоб відтворити помилку. Це було б, якби дія була визначена лише як дія POST. Це дозволяє відтворити помилку за бажанням.

У будь-якому випадку ви можете усунути помилку глобально, як показано нижче. Інша відповідь тут - посилання HandleUnknownActionобробляє лише URL-адреси з неправильними назвами дій, а не з поганими іменами контролерів. Наступний підхід стосується обох.

Додайте це до свого базового контролера (код перегляду тут пропущено):

public ActionResult Error(string errorMessage)
{
    return View("Error");  // or do something like log the error, etc.
}

Додайте глобальний обробник винятків до Global.asax.cs, який викликає метод вище або робить все, що ви хочете зробити із виявленою помилкою 404:

void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();  // get the exception object
    HttpException httpException = ex as HttpException;

    if (httpException != null && httpException.GetHttpCode() == 404)  // if action not found
    {
        string errorMessage = "The requested page was not found.";

        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Base");
        routeData.Values.Add("action", "Error");
        routeData.Values.Add("errorMessage", errorMessage);

        Server.ClearError();
        Response.TrySkipIisCustomErrors = true;

        // Go to our custom error view.
        IController errorController = new BaseController();
        errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.