Ngoại lệ mvc asp.net gián đoạn: “Không thể tìm thấy phương thức hành động công khai ABC trên bộ điều khiển XYZ.”


92

Tôi nhận được một ngoại lệ không liên tục nói rằng asp.net mvc không thể tìm thấy phương thức hành động. Đây là ngoại lệ:

Không thể tìm thấy phương thức hành động công khai 'Fill' trên bộ điều khiển 'Schoon.Form.Web.Controllers.ChrisController'.

Tôi nghĩ rằng tôi đã thiết lập định tuyến chính xác vì ứng dụng này hoạt động hầu hết thời gian. Đây là phương thức hành động của bộ điều khiển.

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

Lộ trình:

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

Và đây là ngăn xếp:

System.Web.HttpException: Không tìm thấy phương thức hành động công khai 'Fill' trên controller 'Schoon.Form.Web.Controllers.ChrisController'. tại System.Web.Mvc.Controller.HandleUnknownAction (String actionName) trong C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs: dòng 197 tại System.Web.Mvc.Controller.ExecuteCore () trong C : \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs: dòng 164 tại System.Web.Mvc.ControllerBase.Execute (RequestContext requestContext) trong C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ ControllerBase.cs: dòng 76 tại System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute (RequestContext requestContext) trong C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ ControllerBase.cs: dòng 87 tại System.Web.Mvc.MvcHandler.ProcessRequest (HttpContextBase httpContext) trong C:

Đây là một ví dụ về các bộ lọc của tôi, tất cả chúng đều hoạt động theo cùng một cách:

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);
    }
}

Cảm ơn, Chris


28
Tôi đã gặp sự cố tương tự mà tôi nghĩ là đáng chú ý ở đây vì đây là kết quả đầu tiên xuất hiện trên Google khi tìm kiếm ngoại lệ ở trên. Ứng dụng của tôi đã ném ra ngoại lệ này khi gửi một biểu mẫu không hợp lệ. Điều này là do trang đang được (hiển thị) gọi RenderAction và hành động được gọi để hiển thị một phần chế độ xem được đánh dấu bằng thuộc tính HttpGet, việc xóa thuộc tính này đã giải quyết được sự cố.
s1mm0t

3
Tôi cũng nhận thấy hành vi này - có lẽ tốt nhất là không áp dụng bất kỳ thuộc tính Http nào cho các phương thức bộ điều khiển trả về PartialViewResults.
Stuart

1
@ s1mm0t: là đúng. đối với trường hợp của tôi, bình luận của mình giải quyết vấn đề
Mazdak Shojaie

@ s1mm0t - vui lòng gửi cho tôi địa chỉ bưu điện của bạn ngay lập tức. Một chai Scotch đang được gửi đến cho bạn vào Giáng sinh này !!!!!
Shane

Chúng tôi đã tìm thấy điều gì đó tương tự: trong một số trường hợp trả về kết quả hành động khác thay vì chuyển hướng đến hành động đó đang gây ra sự cố. Ex PostSomething { return HomePageActionMethod() }không PostSomething { return RedirectToAction(nameof(HomePageActionMethod)); }hoạt động ở đâu . (trong trường hợp của chúng tôi, hành động vi phạm trong chế độ xem nằm trong một bộ điều khiển khác và có lẽ bộ điều khiển đó không được khởi tạo hoàn toàn với phương thức gọi đầu tiên.
jleach

Câu trả lời:


62

Chúng tôi đã tìm ra câu trả lời. Chúng tôi đã xem xét nhật ký web của mình. Nó cho thấy rằng chúng tôi đã nhận được một số hành động http (động từ / phương thức) kỳ lạ như OPTIONS, PROPFIND và HEAD.

Điều này dường như là nguyên nhân của một số trường hợp ngoại lệ. Điều này giải thích tại sao nó không liên tục.

Chúng tôi đã tái tạo sự cố bằng công cụ 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

Cách khắc phục chúng tôi đã sử dụng là thêm phần ủy quyền vào web.config:

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

3
Chúng tôi cũng nhận thấy rằng đôi khi bot sẽ thu thập dữ liệu trang web của bạn - và thậm chí cả javascript - để tìm liên kết. Sau đó, họ thử gửi yêu cầu đến các URI này bằng động từ HTTP sai. Ví dụ: nếu bạn có một lệnh gọi jQuery cho một số hành động - ví dụ / some-action và phương thức này yêu cầu POST, bot có thể cố gắng gửi một GET, điều này sẽ khiến lỗi này hiển thị. Nhật ký web của bạn chắc chắn có thể giúp xác nhận xem có đúng như vậy không. Chúng tôi thậm chí còn thấy googlebot làm điều này.
jakejgordon

Tôi chỉ gặp lỗi này trên máy chủ Trực tiếp (IIS 7.5). Việc triển khai hoạt động tốt trên máy phát triển của tôi cũng như trên máy hỗ trợ khác. thêm các động từ này và xóa HttpGet không khắc phục được sự cố. Mọi đề xuất thêm xin vui lòng.
bjan

Một giải pháp thay thế cho việc từ chối các yêu cầu HEAD đến, bạn có thể muốn đưa ra phản hồi thích hợp. Xem stackoverflow.com/a/3197128/12484
Jon Schneider

15

Chúng tôi đã gặp sự cố tương tự, nhưng nhận thấy rằng nó đang xảy ra vì một người dùng đang đăng bài lên bộ điều khiển sau khi đăng nhập của anh ta hết thời gian. Sau đó hệ thống chuyển đến màn hình đăng nhập. Sau khi đăng nhập, nó được chuyển hướng trở lại URL mà người dùng đang cố gắng đăng lên, nhưng lần này thay vào đó nó đang thực hiện yêu cầu GET và do đó không tìm thấy hành động được đánh dấu bằng thuộc tính [HttpPost].


Giải pháp hiện tại của tôi là luôn thực hiện chuyển hướng trở lại hành động Chỉ mục khi kết thúc một hành động. Xin lỗi vì sự phản ứng chậm.
Johann Strydom

7

Tôi đã gặp vấn đề tương tự trong asp.net mvc. lỗi này - 404 không tìm thấy. Tôi giải quyết vấn đề theo cách này - đặt mã này vào 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

Chúng tôi vừa gặp vấn đề tương tự trên ứng dụng của mình và tôi có thể theo dõi nó là vấn đề javascript / jquery. Chúng tôi có các liên kết trong ứng dụng của chúng tôi được xác định bằng Html.ActionLink () mà sau này được jquery ghi đè thành các POST.

Đầu tiên, chúng tôi đã xác định liên kết:

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

Sau đó, chúng tôi ghi đè hành động mặc định bằng hàm SomePostEventHandler của chúng tôi:

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

Điều này đã đánh trúng hành động MVC của chúng tôi có bộ lọc HttpPost:

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

Những gì chúng tôi nhận thấy là hầu hết thời gian điều này hoạt động tuyệt vời. Tuy nhiên, trên một số trang tải chậm (hoặc người dùng thực sự nhanh), người dùng đã nhấp vào liên kết trước khi sự kiện jquery $ (document) .ready () kích hoạt, có nghĩa là họ đang cố gắng GET / Controller / SomeAction / XX thay vì đăng bài.

Chúng tôi không muốn người dùng NHẬN được url đó, vì vậy việc xóa bộ lọc không phải là một tùy chọn đối với chúng tôi. Thay vào đó, chúng tôi chỉ nối trực tiếp sự kiện onclick của liên kết hành động (chúng tôi đã phải thay đổi một chút SomePostEventHandler () để điều này hoạt động):

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

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

Vì vậy, đạo đức của câu chuyện, đối với chúng tôi, ít nhất là nếu bạn thấy những lỗi này, hãy theo dõi URL mà bạn NGHĨ bạn đang ĐĂNG và đảm bảo rằng bạn đang có.


2

Tôi cũng có vấn đề này.

Trong trường hợp của tôi, nó liên quan đến hạn chế động từ đối với hành động được yêu cầu, trong đó chế độ xem là một chế độ xem POSTtrừ một phần được yêu cầu trong hỗ trợ GETHEADchỉ. Thêm POSTđộng từ vào AcceptVerbsAttribute(trong MVC 1.0) đã giải quyết được vấn đề.


2

Từ nhật ký IIS, sự cố của chúng tôi là do Googlebot cố gắng ĐĂNG và NHẬN cho một hành động điều khiển chỉ POST.

Đối với trường hợp này, tôi khuyên bạn nên xử lý đề xuất 404 như Dmitriy.


1

Câu trả lời hiện được chấp nhận hoạt động như mong đợi nhưng không phải là trường hợp sử dụng chính cho tính năng này. Thay vào đó, hãy sử dụng tính năng được xác định bởi ASP.NET. Trong trường hợp của tôi, tôi đã từ chối mọi thứ ngoại trừ NHẬN và ĐĂNG:

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

Với đoạn mã trên, MVC sẽ trả về một cách chính xác 404


0

Không nên

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

Ngoài ra, bộ lọc của bạn làm gì? Họ không thể ẩn hành động, như ActionMethodSelectorAttribute?


Đó là một lỗi chỉnh sửa. Tôi đã cố gắng bảo vệ người vô tội.
Chris Schoon

Họ điền một số tham số. Ví dụ: UserIdFilter là một trình trợ giúp để lấy id người dùng từ session / cookie / v.v. Nó điền tham số đầu tiên. Tôi sẽ chỉnh sửa bài đăng để bao gồm nó.
Chris Schoon

0

Tôi gặp sự cố tương tự với Tải lên tệp qq

Khi hành động đăng là /Document/Savetôi nhận được ngoại lệ Một phương thức hành động công khai 'Lưu' không được tìm thấy trên bộ điều khiển 'Project.Controllers.DocumentController'.

Nhưng nếu hành động đăng là /Document/Save/ đăng là đúng, bài đăng là chính xác và hoạt động!

Chúa cứu con / ?


0

Nguyên nhân gốc rễ của tôi tương tự như nguyên nhân được đề cập trong bình luận.

Tôi là ajaxSubmittingmột hình thức khi nhấp vào một nút. Một trong các trường biểu mẫu thuộc loại Date. Tuy nhiên, do sự khác biệt về định dạng ngày giữa máy khách và máy chủ, nó không thực thi phương thức POST trong bộ điều khiển. Máy chủ đã gửi lại 302phản hồi và sau đó gửi lại GETyêu cầu cho cùng một phương pháp.

Tuy nhiên, hành động trong bộ điều khiển được trang trí bằng HttpPostthuộc tính và do đó nó không thể tìm thấy phương thức và gửi lại 404phản hồi.

Tôi vừa sửa mã sao cho sự không khớp trong các định dạng Ngày tháng sẽ không gây ra lỗi và sự cố đã được khắc phục.


0

Loại bỏ các [HttpGet]thuộc tính và nó sẽ hoạt động :)


Mặc dù điều này "giải quyết" các lỗi, khả năng là bạn (hoặc ai đó trước bạn) đặt các [HttpGet]thuộc tính đó có mục đích, để ngăn các hành động được gọi thông qua bất kỳ ĐỘNG TỪ nào khác
Nick Orlando

0

Đối với bất kỳ ai gặp sự cố này với chèn kiểu anglejs, MVC và {{imagepath}} trong thuộc tính src của hình ảnh, ví dụ:

"Không tìm thấy phương pháp hành động công khai '{{imagepath}} before.png' trên bộ điều khiển"

Giải pháp là sử dụng ng-src thay vì src.

Hy vọng điều này sẽ giúp ai đó :)


gần một năm sau, tôi đã tìm kiếm điều này :) tnx!
Verthosa,

0

Xem liệu chỉ cần duyệt đến URL được đề cập là đủ để tạo ra lỗi. Nó sẽ xảy ra nếu hành động chỉ được xác định là một hành động ĐĂNG. Làm điều này cho phép bạn tạo lại lỗi theo ý muốn.

Trong mọi trường hợp, bạn có thể xử lý toàn bộ lỗi như bên dưới. Một câu trả lời khác ở đây tham chiếu HandleUnknownActionchỉ xử lý các URL có tên hành động xấu, không phải tên bộ điều khiển xấu. Cách tiếp cận sau đây xử lý cả hai.

Thêm cái này vào bộ điều khiển cơ sở của bạn (mã xem được bỏ qua ở đây):

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

Thêm trình xử lý ngoại lệ toàn cục vào Global.asax.cs gọi phương thức ở trên hoặc thực hiện bất kỳ điều gì khác bạn muốn làm với lỗi 404 đã mắc:

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));
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.