간헐적 인 asp.net mvc 예외 : "공개 작업 방법 ABC를 컨트롤러 XYZ에서 찾을 수 없습니다."


92

asp.net mvc에서 작업 방법을 찾을 수 없다는 간헐적 인 예외가 발생합니다. 예외는 다음과 같습니다.

컨트롤러 'Schoon.Form.Web.Controllers.ChrisController'에서 공개 작업 메서드 'Fill'을 찾을 수 없습니다.

이 응용 프로그램이 대부분 작동하기 때문에 라우팅이 올바르게 설정되어 있다고 생각합니다. 다음은 컨트롤러의 동작 방법입니다.

[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'컨트롤러에서 공용 작업 메서드 'Fill'을 찾을 수 없습니다. C : \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs : line 197의 System.Web.Mvc.Controller.HandleUnknownAction (String actionName)에서 C의 System.Web.Mvc.Controller.ExecuteCore ()에서 : \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs : line 164 at System.Web.Mvc.ControllerBase.Execute (RequestContext requestContext) in C : \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ ControllerBase.cs : line 76 at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute (RequestContext requestContext) in C : \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ ControllerBase.cs : line 87 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
이 동작도 발견했습니다. PartialViewResults를 반환하는 컨트롤러 메서드에 Http 속성을 적용하지 않는 것이 가장 좋습니다.
Stuart

1
@ s1mm0t : 맞습니다. 내 경우에, 그의 코멘트는 문제 해결
마즈 다크 교 Shojaie

@ s1mm0t-우편 주소를 즉시 보내주세요. 이번 크리스마스에 스카치 한 병이옵니다 !!!!!
Shane

비슷한 것을 발견했습니다. 어떤 경우에는 해당 작업으로의 리디렉션 대신 다른 작업 결과를 반환하는 것이 문제를 일으켰습니다. Ex PostSomething { return HomePageActionMethod() }PostSomething { return RedirectToAction(nameof(HomePageActionMethod)); }작동하는 곳에서 실패 합니다. (우리의 경우에 뷰의 잘못된 동작이 다른 제어기에 있으며 제어기는 호출 완전히 첫 번째 방법으로 초기화되지 않은 것으로 추측.
jleach

답변:


62

답을 찾았습니다. 우리는 웹 로그를 조사했습니다. OPTIONS, PROPFIND 및 HEAD와 같은 이상한 http 작업 (동사 / 메서드)을 수신하는 것으로 나타났습니다.

이것은 일부 논문 예외의 원인으로 보입니다. 이것은 간헐적 인 이유를 설명합니다.

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
또한 봇이 링크를 찾기 위해 때때로 귀하의 사이트, 심지어는 자바 스크립트를 크롤링하는 것으로 나타났습니다. 그런 다음 잘못된 HTTP 동사를 사용하여 이러한 URI에 요청을 보내려고합니다. 예를 들어, 어떤 작업에 대한 jQuery 호출 (예 : / some-action)이 있고이 메서드에 POST가 필요한 경우 봇은 GET 전송을 시도 할 수 있으며 이로 인해이 오류가 표시됩니다. 웹 로그는 이것이 사실인지 확인하는 데 확실히 도움이 될 수 있습니다. Googlebot도이 작업을 수행합니다.
jakejgordon

라이브 서버 (IIS 7.5)에서만 이와 동일한 오류가 발생합니다. 배포는 내 개발 컴퓨터와 다른 지원 컴퓨터에서 잘 작동합니다. 이 동사를 추가하고 HttpGet을 제거해도 문제가 해결되지 않았습니다. 추가 제안이 있으시면 부탁드립니다.
bjan

들어오는 HEAD 요청을 거부하는 대신 적절한 응답을 제공 할 수 있습니다. stackoverflow.com/a/3197128/12484
Jon Schneider

15

비슷한 문제가 있었지만 사용자가 로그인 시간이 초과 된 후 컨트롤러에 게시했기 때문에 발생하는 것으로 나타났습니다. 그런 다음 시스템은 로그인 화면으로 리디렉션됩니다. 로그인 후 사용자가 게시하려는 URL로 다시 리디렉션되었지만 이번에는 대신 GET 요청을 수행했기 때문에 [HttpPost] 속성으로 표시된 작업을 찾지 못했습니다.


내 현재 솔루션은 가능한 한 작업이 끝날 때 항상 Index 작업으로 다시 리디렉션하는 것입니다. 답장을 늦게 보내서 미안해.
Johann Strydom 2011

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 문제를 추적 할 수있었습니다. 나중에 jquery에 의해 POST로 재정의되는 Html.ActionLink ()를 사용하여 정의 된 응용 프로그램에 링크가 있습니다.

먼저 링크를 정의했습니다.

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

나중에 SomePostEventHandler 함수로 기본 작업을 재정의합니다.

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

이것은 HttpPost 필터가있는 MVC 작업에 부딪 혔습니다.

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

우리가 찾은 것은 대부분의 경우 이것이 훌륭하게 작동한다는 것입니다. 그러나 일부 느린 페이지로드 (또는 정말 빠른 사용자)에서 사용자는 jquery $ (document) .ready () 이벤트가 발생하기 전에 링크를 클릭했습니다. 즉, 전기.

사용자가 해당 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만 요청되었습니다 . (MVC 1.0에서) POST동사를 추가하면 AcceptVerbsAttribute문제가 해결되었습니다.


2

IIS 로그에서 문제는 Googlebot이 POST를 시도하고 POST 전용 컨트롤러 작업에 대한 GET으로 인해 발생했습니다.

이 경우 Dmitriy 제안과 같은 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와 같은 작업을 숨길 수 없습니까?


그것은 편집 실수입니다. 무고한자를 보호하려고 했어요
Chris Schoon

일부 매개 변수를 채 웁니다. 예를 들어 UserIdFilter는 세션 / 쿠키 등에서 사용자 ID를 가져 오는 도우미입니다. 첫 번째 매개 변수를 채 웁니다. 게시물을 포함하도록 편집하겠습니다.
Chris Schoon

0

qq 파일 업로드 와 비슷한 문제가 있습니다.

게시 작업이 /Document/Save발생하면 예외가 발생 합니다. 'Project.Controllers.DocumentController'컨트롤러에서 공개 작업 메서드 'Save'를 찾을 수 없습니다.

그러나 포스트 액션이 /Document/Save/ 이면 포스트가 정확하고 작동합니다!

하나님은 / ?


0

내 근본 원인은 댓글에 언급 된 것과 유사했습니다.

나는 ajaxSubmitting버튼을 클릭하면 양식 이었다 . 양식 필드 중 하나가 Date. 그러나 클라이언트와 서버 시스템 간의 날짜 형식이 다르기 때문에 컨트롤러에서 POST 메서드를 실행하지 않았습니다. 서버는 302응답을 다시 보낸 다음 GET동일한 메서드에 대한 요청을 다시 보냈습니다 .

그러나 컨트롤러의 작업은 HttpPost속성 으로 장식 되었으므로 메서드를 찾을 수없고 404응답을 다시 보냈습니다 .

날짜 형식의 불일치로 인해 오류가 발생하지 않고 문제가 수정되도록 코드를 수정했습니다.


0

[HttpGet]속성을 제거하면 작동합니다. :)


이렇게하면 오류가 "해결"되지만 [HttpGet]다른 동사를 통해 작업이 호출되는 것을 방지하기 위해 사용자 (또는 이전 사람)가 의도적으로 해당 속성을 넣을 가능성이 있습니다.
Nick Orlando

0

angularjs, MVC 및 {{imagepath}} 유형에이 문제가있는 사람은 이미지 src 속성에 삽입합니다. 예 :

"컨트롤러에서 '{{imagepath}} previous.png'공개 작업 방법을 찾을 수 없습니다."

해결책은 src 대신 ng-src를 사용하는 것입니다.

이것이 누군가에게 도움이되기를 바랍니다 :)


거의 1 년 후, 나는 이것을 찾고 있었다 :) tnx!
Verthosa

0

문제의 URL을 검색하는 것만으로도 오류를 재현 할 수 있는지 확인하십시오. 작업이 POST 작업으로 만 정의 된 경우입니다. 이렇게하면 오류를 마음대로 재현 할 수 있습니다.

어쨌든 아래와 같이 오류를 전역 적으로 처리 할 수 ​​있습니다. 참조하는 또 다른 답변은 HandleUnknownAction잘못된 컨트롤러 이름이 아닌 잘못된 작업 이름이있는 URL 만 처리합니다. 다음 접근 방식은 둘 다 처리합니다.

이것을 기본 컨트롤러에 추가하십시오 (여기에서 코드보기 생략).

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

위의 메서드를 호출하거나 잡힌 404 오류에 대해 원하는 작업을 수행하는 Global.asax.cs에 전역 예외 처리기를 추가합니다.

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));
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.