Perutean untuk halaman kesalahan 404 ASP.NET MVC kustom

116

Saya mencoba membuat halaman kesalahan HTTP 404 kustom ketika seseorang mengetikkan URL yang tidak menjalankan tindakan atau pengontrol yang valid di ASP.NET MVC, alih-alih menampilkan kesalahan ASP.NET generik "Resource Not Found".

Saya tidak ingin menggunakan web.config untuk menangani ini.

Apakah ada sihir perutean yang dapat saya lakukan untuk menangkap URL yang tidak valid?

Pembaruan: Saya mencoba jawaban yang diberikan, namun saya masih mendapatkan pesan "Resource Not Found" yang jelek.

Pembaruan lain: Ok, ternyata ada yang berubah di RC1. Saya bahkan telah mencoba secara khusus menjebak 404 pada sebuah HttpExceptiondan masih memberi saya halaman "Sumber Daya Tidak Ditemukan".

Saya bahkan telah menggunakan fitur sumber daya MvcContrib dan tidak ada - masalah yang sama. Ada ide?

dswatik
sumber
@Peter Itu adalah solusi yang saya tambahkan bersama dengan menimpa HandleUnknownAction untuk menampilkan tampilan halaman tidak ditemukan ketika tindakan tidak ada dan kemudian built in ASP.net custom error handler untuk menangani hal lain miring yang dapat diketik pengguna .
dswatik
@pete Ini juga berfungsi stackoverflow.com/questions/619895/…
dswatik
8
Saya benci jika pengguna lain sombong dan mengatakan hal-hal seperti, "mengapa Anda ingin melakukan itu? Lakukan saja ini ..." Tetapi saya menyarankan bahwa jika tidak ada yang menghentikan Anda dari menggunakan pendekatan web.config dan itu memenuhi kebutuhan Anda, ini adalah pendekatan standar dan elegan. Setiap umpan balik tentang pendekatan itu dihargai, karena mungkin ada beberapa masalah dengannya yang tidak saya ketahui.
Sean

Jawaban:

10

Cukup tambahkan tangkap semua rute di akhir tabel rute dan tampilkan halaman apa pun yang Anda inginkan dengannya.

Lihat: Bagaimana cara membuat rute tangkap semua untuk menangani kueri '404 halaman tidak ditemukan' untuk ASP.NET MVC?

Alex Reitbort
sumber
Saya mencoba ini namun, saya masih mendapatkan pesan sumber daya tidak ditemukan default ASP.NET jelek ..
dswatik
3
Saya tidak menemukan solusi yang pasti (dan fleksibel !!) untuk masalah ini baik dalam jawaban ini maupun pada tautan yang disediakan.
Peter
4
Aku juga tidak ... ini sepertinya jawaban yang menjebak. Saya mencari lebih banyak cara untuk membuat customErrors berperilaku seperti yang mereka lakukan di WebForms. Ada ide?
JC Grubbs
1
Keduanya tidak berhasil & buruk pada prinsipnya. Tidak berfungsi karena tidak akan menangkap URL buruk yang cocok dengan salah satu pola perutean sebelumnya. Buruk pada prinsipnya karena mengubah apa yang seharusnya menjadi kesalahan menjadi bukan kesalahan. Mengarahkan ke halaman yang Anda beri nama "Error" berbeda dengan mengarahkan ke halaman kesalahan. Anda ingin menyimpannya sebagai kesalahan, mencatat kesalahan tersebut, lalu menanganinya sebagai kesalahan. Kesalahan adalah informasi yang berharga.
Matius
105

Saya sudah mencoba mengaktifkan kesalahan khusus pada server produksi selama 3 jam, sepertinya saya menemukan solusi akhir bagaimana melakukan ini di ASP.NET MVC tanpa rute apa pun.

Untuk mengaktifkan kesalahan khusus dalam aplikasi ASP.NET MVC yang kita butuhkan (IIS 7+):

  1. Konfigurasikan halaman kustom di konfigurasi web di bawah system.webbagian:

    <customErrors mode="RemoteOnly"  defaultRedirect="~/error">
        <error statusCode="404" redirect="~/error/Error404" />
        <error statusCode="500" redirect="~/error" />
    </customErrors>
    

    RemoteOnlyartinya di jaringan lokal Anda akan melihat kesalahan nyata (sangat berguna selama pengembangan). Kami juga dapat menulis ulang halaman kesalahan untuk kode kesalahan apa pun.

  2. Setel parameter Respon ajaib dan kode status respon (dalam modul penanganan kesalahan atau dalam atribut penanganan kesalahan)

      HttpContext.Current.Response.StatusCode = 500;
      HttpContext.Current.Response.TrySkipIisCustomErrors = true;
    
  3. Tetapkan pengaturan ajaib lain di konfigurasi web di bawah system.webServerbagian:

    <httpErrors errorMode="Detailed" />

Ini adalah hal terakhir yang saya temukan dan setelah ini saya dapat melihat kesalahan khusus pada server produksi.

Andrew Orsich
sumber
8
Ini masih bukan solusi yang ideal. Itu tidak memberi Anda kode respons HTTP yang tepat. Menggunakan customErrorshasil dalam pengalihan 302 hanya untuk memuat halaman kesalahan Anda.
Justin Helgerson
@ Ek0nomik Saya belum pernah melihat solusi yang ideal :)
Andrew Orsich
2
@JustinHelgerson Saya menyiapkan ErrorController untuk setiap kode status dan menetapkan Kode Respons di dalam tindakan tersebut dan menyetel kode respons dengan baik .. Saya menguji dengan Fiddler dan kode status 404 merespons dengan 404 dan halaman dengan 500 kesalahan merespons dengan 500. Dan dalam kedua kasus, tampilan kesalahan khusus saya ditampilkan
Shane Neuville
rekan satu tim saya baru saja menghapus tampilan Kesalahan di bawah folder Bersama , untuk membuat kesalahan runtime dengan kode status 500 untuk mengarahkan ke Halaman Kesalahan Kustom seperti yang disebutkan di sini dan di sini . Harapan membantu seseorang.
shaijut
41

Saya mendapatkan penanganan kesalahan saya untuk bekerja dengan membuat ErrorController yang mengembalikan tampilan dalam artikel ini. Saya juga harus menambahkan "Catch All" ke rute di global.asax.

Saya tidak dapat melihat bagaimana ini akan sampai ke salah satu halaman kesalahan ini jika tidak ada di Web.config ..? Web.config saya harus menentukan:

customErrors mode="On" defaultRedirect="~/Error/Unknown"

dan kemudian saya juga menambahkan:

error statusCode="404" redirect="~/Error/NotFound"
Jack Smit
sumber
2
Terima kasih - itu membantu saya, 2 tahun kemudian! Apa yang Anda lakukan jika Anda hanya menginginkan kesalahan kustom untuk 404, tidak ada yang lain?
Shaul Behr
1
@Shaul setahun kemudian ... jangan setel defaultRedirect, kecualikan atribut sama sekali.
NJE
27

Sumber

NotFoundMVC - Menyediakan halaman 404 yang mudah digunakan setiap kali pengontrol, tindakan, atau rute tidak ditemukan di aplikasi ASP.NET MVC3 Anda. Tampilan yang disebut NotFound diberikan alih-alih halaman galat ASP.NET default.

Anda dapat menambahkan plugin ini melalui nuget menggunakan: Install-Package NotFoundMvc

NotFoundMvc otomatis menginstal sendiri saat aplikasi web dimulai. Ini menangani semua cara berbeda 404 HttpException biasanya dilemparkan oleh ASP.NET MVC. Ini termasuk pengontrol, tindakan, dan rute yang hilang.

Panduan Instalasi Langkah demi Langkah:

1 - Klik kanan pada Proyek Anda dan Pilih Kelola Paket Nuget ...

2 - Cari NotFoundMvcdan instal. masukkan deskripsi gambar di sini

3 - Setelah penginstalan selesai, dua file akan ditambahkan ke proyek Anda. Seperti yang ditunjukkan pada tangkapan layar di bawah ini.

masukkan deskripsi gambar di sini

4 - Buka NotFound.cshtml yang baru ditambahkan di Views / Shared dan ubah sesuka Anda. Sekarang jalankan aplikasi dan ketik url yang salah, dan Anda akan disambut dengan halaman 404 yang ramah pengguna.

masukkan deskripsi gambar di sini

Tidak lebih, pengguna akan mendapatkan pesan kesalahan seperti Server Error in '/' Application. The resource cannot be found.

Semoga ini membantu :)

PS: Kudos to Andrew Davey karena telah membuat plugin yang luar biasa.

Yasser Shaikh
sumber
@niico Dari melihat kode sumber tampaknya mengatur kode respon ke 404, jadi ya.
Akankah Dean
20

Coba ini di web.config untuk mengganti halaman kesalahan IIS. Ini adalah solusi terbaik yang saya rasa, dan mengirimkan kode status yang benar juga.

<system.webServer>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" subStatusCode="-1" />
    <remove statusCode="500" subStatusCode="-1" />
    <error statusCode="404" path="Error404.html" responseMode="File" />
    <error statusCode="500" path="Error.html" responseMode="File" />
  </httpErrors>
</system.webServer>

Info lebih lanjut dari Tipila - Gunakan Halaman Kesalahan Kustom ASP.NET MVC

Amila
sumber
1
+1. Ini adalah satu-satunya hal yang tampaknya bekerja secara konsisten untuk saya di MVC5 dengan banyak area.
hawkke
Ini adalah solusi termudah. Anda tidak dapat menggunakan sintaks pisau cukur di halaman kesalahan Anda.
highace
15

Solusi ini tidak memerlukan perubahan file web.config atau rute penampung semua.

Pertama, buat pengontrol seperti ini;

public class ErrorController : Controller
{
    public ActionResult Index()
    {
        ViewBag.Title = "Regular Error";
        return View();
    }

    public ActionResult NotFound404()
    {
        ViewBag.Title = "Error 404 - File not Found";
        return View("Index");
    }
}

Kemudian buat tampilan di bawah "Views / Error / Index.cshtml" sebagai;

 @{
      Layout = "~/Views/Shared/_Layout.cshtml";
  }                     
  <p>We're sorry, page you're looking for is, sadly, not here.</p>

Kemudian tambahkan yang berikut ini di file asax Global seperti di bawah ini:

protected void Application_Error(object sender, EventArgs e)
{
        // Do whatever you want to do with the error

        //Show the custom error page...
        Server.ClearError(); 
        var routeData = new RouteData();
        routeData.Values["controller"] = "Error";

        if ((Context.Server.GetLastError() is HttpException) && ((Context.Server.GetLastError() as HttpException).GetHttpCode() != 404))
        {
            routeData.Values["action"] = "Index";
        }
        else
        {
            // Handle 404 error and response code
            Response.StatusCode = 404;
            routeData.Values["action"] = "NotFound404";
        } 
        Response.TrySkipIisCustomErrors = true; // If you are using IIS7, have this line
        IController errorsController = new ErrorController();
        HttpContextWrapper wrapper = new HttpContextWrapper(Context);
        var rc = new System.Web.Routing.RequestContext(wrapper, routeData);
        errorsController.Execute(rc);

        Response.End();
}

Jika Anda masih mendapatkan halaman kesalahan IIS kustom setelah melakukan ini, pastikan bagian berikut diberi komentar (atau kosong) di file konfigurasi web:

<system.web>
   <customErrors mode="Off" />
</system.web>
<system.webServer>   
   <httpErrors>     
   </httpErrors>
</system.webServer>
Sujeewa
sumber
Saya tidak berpikir pendekatan ini akan berhasil di semua contoh, karena 404 sering dicegat oleh server web dan oleh karena itu tidak pernah ditangani di tingkat aplikasi.
Chris Halcrow
Saya ingin menambahkan bahwa jika Anda menggunakan pendekatan ini, saya akan merekomendasikan menambahkan a Response.End();di akhir penangan Application_Error Anda. Tanpa ini, hanya kemunculan kesalahan pertama yang dipicu untuk sesi tertentu, yang merupakan masalah ketika Anda memiliki, misalnya, pencatatan kesalahan khusus di penangan Application_Error.
Keith
6

Jika Anda bekerja di MVC 4, Anda dapat menonton solusi ini , itu berhasil untuk saya.

Tambahkan metode Application_Error berikut ke my Global.asax:

protected void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    Server.ClearError();

    RouteData routeData = new RouteData();
    routeData.Values.Add("controller", "Error");
    routeData.Values.Add("action", "Index");
    routeData.Values.Add("exception", exception);

    if (exception.GetType() == typeof(HttpException))
    {
        routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
    }
    else
    {
        routeData.Values.Add("statusCode", 500);
    }

    IController controller = new ErrorController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();

Pengontrolnya sendiri sangat sederhana:

public class ErrorController : Controller
{
    public ActionResult Index(int statusCode, Exception exception)
    {
        Response.StatusCode = statusCode;
        return View();
    }
}

Periksa kode sumber lengkap Mvc4CustomErrorPage di GitHub .

Duc Hoang
sumber
0

Saya memiliki masalah yang sama, hal yang harus Anda lakukan adalah, alih-alih menambahkan atribut customErrors di file web.config di folder Views Anda, Anda harus menambahkannya di file web.config di folder root proyek Anda

SmokeIT
sumber
0

Berikut adalah jawaban yang benar yang memungkinkan sepenuhnya menyesuaikan halaman kesalahan di satu tempat. Tidak perlu memodifikasi web.config atau membuat kode terpisah.

Bekerja juga di MVC 5.

Tambahkan kode ini ke pengontrol:

        if (bad) {
            Response.Clear();
            Response.TrySkipIisCustomErrors = true;
            Response.Write(product + I(" Toodet pole"));
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            //Response.ContentType = "text/html; charset=utf-8";
            Response.End();
            return null;
        }

Berdasarkan http://www.eidias.com/blog/2014/7/2/mvc-custom-error-pages

Andrus
sumber
0

Saya akan berbicara tentang beberapa kasus tertentu,

jika Anda menggunakan 'metode PageNotFound' di HomeController seperti di bawah ini

[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

ini tidak akan berhasil. Tetapi Anda harus menghapus tag Rute seperti di bawah ini,

//[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

Dan jika Anda mengubahnya sebagai Nama metode di web.config itu berfungsi. Namun jangan lupa untuk melakukan kode seperti di bawah ini di web.config

<customErrors mode="On">
  <error statusCode="404" redirect="~/PageNotFound" /> 
 *// it is not "~/404" because it is not accepted url in Route Tag like [Route("404")]*
</customErrors>
Furkan ozturk
sumber