ASP.NET MVC 404 Error Handling

I've membuat perubahan yang diuraikan di https://stackoverflow.com/questions/108813/404-http-error-handler-in-aspnet-mvc-rc-5 dan saya'm masih mendapatkan standar error 404 halaman. Apakah saya perlu mengubah sesuatu di IIS?

Mengomentari pertanyaan (1)

I've diselidiki BANYAK bagaimana untuk benar mengelola 404s di MVC (khusus MVC3), dan ini, IMHO adalah solusi terbaik saya've datang dengan:

Di global.asax:

public class MvcApplication : HttpApplication
{
    protected void Application_EndRequest()
    {
        if (Context.Response.StatusCode == 404)
        {
            Response.Clear();

            var rd = new RouteData();
            rd.DataTokens["area"] = "AreaName"; // In case controller is in another area
            rd.Values["controller"] = "Errors";
            rd.Values["action"] = "NotFound";

            IController c = new ErrorsController();
            c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
        }
    }
}

ErrorsController:

public sealed class ErrorsController : Controller
{
    public ActionResult NotFound()
    {
        ActionResult result;

        object model = Request.Url.PathAndQuery;

        if (!Request.IsAjaxRequest())
            result = View(model);
        else
            result = PartialView("_NotFound", model);

        return result;
    }
}

Edit:

Jika anda're menggunakan IoC (misalnya AutoFac), anda harus membuat controller menggunakan:

var rc = new RequestContext(new HttpContextWrapper(Context), rd);
var c = ControllerBuilder.Current.GetControllerFactory().CreateController(rc, "Errors");
c.Execute(rc);

Bukan

IController c = new ErrorsController();
c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));

(Opsional)

Penjelasan:

Ada 6 skenario yang saya bisa memikirkan mana yang ASP.NET MVC3 aplikasi dapat menghasilkan 404.

Yang dihasilkan oleh ASP.NET:

  • Skenario 1: URL tidak sesuai rute dalam tabel rute.

Yang dihasilkan oleh ASP.NET MVC:

  • Skenario 2: URL pertandingan rute, tapi menentukan controller yang doesn't ada.

  • Skenario 3: URL pertandingan rute, tapi menentukan sebuah tindakan yang doesn't ada.

Manual yang dihasilkan:

  • Skenario 4: An aksi kembali sebuah HttpNotFoundResult dengan menggunakan metode HttpNotFound().

  • Skenario 5: tindakan melempar HttpException dengan kode status 404.

  • Skenario 6: Sebuah tindakan manual memodifikasi Respon.StatusCode properti untuk 404.

Tujuan

  • (Pusat) Menunjukkan custom halaman error 404 untuk pengguna.

  • (B) Menjaga kode status 404 pada respon klien (khususnya penting untuk SEO).

  • (C) Kirim tanggapan secara langsung, tanpa melibatkan 302 pengalihan.

Solusi Usaha: Kesalahan Kustom





Masalah dengan solusi ini:

  • Tidak sesuai dengan tujuan (A) dalam skenario (1), (4), (6).
  • Tidak sesuai dengan tujuan (B) secara otomatis. Itu harus diprogram secara manual.
  • Tidak sesuai dengan tujuan (C).

Solusi Usaha: HTTP Kesalahan






Masalah dengan solusi ini:

  • Hanya bekerja pada IIS 7+.
  • Tidak sesuai dengan tujuan (A) dalam skenario (2), (3), (5).
  • Tidak sesuai dengan tujuan (B) secara otomatis. Itu harus diprogram secara manual.

Solusi Usaha: HTTP Kesalahan dengan Mengganti






Masalah dengan solusi ini:

  • Hanya bekerja pada IIS 7+.
  • Tidak sesuai dengan tujuan (B) secara otomatis. Itu harus diprogram secara manual.
  • Mengaburkan tingkat aplikasi http pengecualian. E. g. bisa't menggunakan customErrors bagian, Sistem.Web.Mvc.HandleErrorAttribute, dll. Hal ini dapat't hanya menunjukkan kesalahan umum halaman.

Solusi Upaya customErrors dan HTTP Kesalahan





dan






Masalah dengan solusi ini:

  • Hanya bekerja pada IIS 7+.
  • Tidak sesuai dengan tujuan (B) secara otomatis. Itu harus diprogram secara manual.
  • Tidak sesuai dengan tujuan (C) dalam skenario (2), (3), (5).

Orang-orang yang bermasalah dengan hal ini bahkan sebelum mencoba untuk membuat perpustakaan sendiri (lihat http://aboutcode.net/2011/02/26/handling-not-found-with-asp-net-mvc3.html). Tapi sebelumnya solusi tampaknya untuk menutupi semua skenario tanpa kompleksitas menggunakan perpustakaan eksternal.

Komentar (26)
Larutan

Namun solusi lain.

Tambahkan ErrorControllers atau halaman statis dengan 404 kesalahan informasi.

Memodifikasi web anda.config (dalam kasus controller).





Atau dalam kasus halaman statis





Ini akan menangani kedua terjawab rute dan tindakan tidak terjawab.

Komentar (11)

Respon dari Marco adalah solusi TERBAIK. Saya perlu untuk mengontrol kesalahan penanganan, dan maksud saya benar-benar mengendalikannya. Tentu saja, saya telah diperpanjang solusi sedikit dan dibuat penuh kesalahan sistem manajemen yang mengelola segala sesuatu. Saya juga membaca tentang solusi ini di blog lain dan tampaknya sangat dapat diterima oleh sebagian besar pengembang maju.

Berikut ini adalah kode akhir yang saya gunakan:

protected void Application_EndRequest()
    {
        if (Context.Response.StatusCode == 404)
        {
            var exception = Server.GetLastError();
            var httpException = exception as HttpException;
            Response.Clear();
            Server.ClearError();
            var routeData = new RouteData();
            routeData.Values["controller"] = "ErrorManager";
            routeData.Values["action"] = "Fire404Error";
            routeData.Values["exception"] = exception;
            Response.StatusCode = 500;

            if (httpException != null)
            {
                Response.StatusCode = httpException.GetHttpCode();
                switch (Response.StatusCode)
                {
                    case 404:
                        routeData.Values["action"] = "Fire404Error";
                        break;
                }
            }
            // Avoid IIS7 getting in the middle
            Response.TrySkipIisCustomErrors = true;
            IController errormanagerController = new ErrorManagerController();
            HttpContextWrapper wrapper = new HttpContextWrapper(Context);
            var rc = new RequestContext(wrapper, routeData);
            errormanagerController.Execute(rc);
        }
    }

dan di dalam saya ErrorManagerController :

        public void Fire404Error(HttpException exception)
    {
        //you can place any other error handling code here
        throw new PageNotFoundException("page or resource");
    }

Sekarang, dalam Tindakan saya, saya melemparkan Pengecualian Kustom yang saya telah dibuat. Dan saya Controller adalah pewarisan dari custom Controller Berbasis kelas yang saya telah dibuat. Custom Base Controller diciptakan untuk mengesampingkan penanganan kesalahan. Berikut ini adalah kebiasaan saya Dasar kelas Controller:

public class MyBasePageController : Controller
{
    protected override void OnException(ExceptionContext filterContext)
    {
        filterContext.GetType();
        filterContext.ExceptionHandled = true;
        this.View("ErrorManager", filterContext).ExecuteResult(this.ControllerContext);
        base.OnException(filterContext);
    }
}

"ErrorManager" pada kode diatas adalah sekedar tampilan yang menggunakan Model yang didasarkan pada ExceptionContext

Solusi saya bekerja sempurna dan saya mampu menangani SETIAP error yang terjadi pada website saya dan menampilkan pesan yang berbeda berdasarkan pada SETIAP jenis pengecualian.

Komentar (1)

Di IIS, anda dapat menentukan redirect ke "tertentu" di halaman berdasarkan kode kesalahan. Di anda contoh, anda dapat mengkonfigurasi 404 - > Anda disesuaikan 404 error page.

Komentar (0)

Apa yang bisa saya rekomendasikan adalah dengan melihat pada FilterAttribute. Misalnya MVC sudah memiliki HandleErrorAttribute. Anda dapat menyesuaikannya untuk menangani hanya 404. Balasan jika anda loi saya akan melihat contoh.

BTW

Solusi(dengan rute terakhir) bahwa anda telah diterima di pertanyaan sebelumnya tidak bekerja di banyak situasi. Solusi kedua dengan HandleUnknownAction akan bekerja tetapi membutuhkan untuk membuat perubahan ini dalam setiap controller atau untuk memiliki satu dasar controller.

Pilihan saya adalah larutan dengan HandleUnknownAction.

Komentar (4)