SORU
6 Mart 2009, Cuma


Nasıl düzgün ASP.NET MVC 404 işleyebilir miyim?

Sadece benimle ASP.NET MVC çok ayı yeni başlıyorum. Site ve çeşitli diğerleri bu civarında aradım ve bu birkaç uygulamaları gördük.

EDİT: RC2 kullanıyorum söylemeyi unutmuşum

URL Yönlendirme kullanma

routes.MapRoute(
    "Error",
     "{*url}",
     new { controller = "Errors", action = "NotFound" }  // 404s
);

Yukarıdaki bu gibi istekleri (varsayarak varsayılan rota tabloları ilk MVC projesi tarafından Kur) dikkat çekmek gibi görünüyor: "" . /bla/bla/bla/bla

() Geçersiz kılma HandleUnknownAction denetleyicisi kendisi

// 404s - handle here (bad action requested
protected override void HandleUnknownAction(string actionName) {
    ViewData["actionName"] = actionName;
    View("NotFound").ExecuteResult(this.ControllerContext);
}  

Ancak önceki stratejileri Kötü/Bilinmeyen bir denetleyici için bir istek işleyemez. Örneğin, bir "yönlendirme geçersiz kullanırsam", eğer bu isteği web sunucusu genel 404 sayfa ve benim 404 Not alıyorum. İDoNotExist/yok

Sonunda, benim sorum:Bu tür istek, bir rota veya MVC çerçevesinde başka bir şey kullanmadan yakalamak için herhangi bir şekilde kendisini var mı?

YA da sadece Web kullanarak varsayılan gerekir.Benim 404 işleyicisi olarak Config customErrors ve tüm bu unutmak? Eğer /Web Görüşleri nedeniyle dışında genel 404 sayfa depolamak lazım customErrors ile gidersem sanırım.Doğrudan erişim kısıtlamaları Config. Zaten en iyi uygulamalar veya herhangi bir rehberlik takdir edilir.

CEVAP
5 NİSAN 2010, PAZARTESİ


404 gereksinimleri

Aşağıdaki 404 çözümü için, ihtiyaçlarına ve ben aşağıda nasıl yapılacağını göster ben bunu uygulamak:

  • Kötü eylemleri ile eşleşti yolları işlemek istiyorum
  • Kötü denetleyicileri ile eşleşti yolları işlemek istiyorum
  • Uyumlu un yolları (uygulamam anlayamayan keyfi URL) kontrol etmek istiyorum - bu dünya kadar köpüren istemiyorum.çünkü o zaman asax veya IIS 26**
  • Bir yol üstünde, özel olarak aynı şekilde bir KİMLİK var olmayan bir nesne için gönderildiğinde gibi 404'ler - (belki silinmiş) ele almak istiyorum
  • Benim 404 hataları için gerekirse daha fazla veri daha sonra pompa edebilirim MVC görünümü (statik sayfa) (good 404 designs) geri dönmek istiyorumveonlargerekirHTTP 404 durum kodunu döndürür

Çözüm

Genel Application_Error kaydetmek gerektiğini düşünüyorum.işlenmeyen özel durumlar ve günlüğü (Shay Jacoby's answer gösterir gibi) gibi yüksek bir şey için asax ama 404 işleme. Bu benim önerim Global dışarı 404 tutuyor neden olur.dosya asax.

Adım 1: 404-hata mantık . için ortak bir yer Var

Bu sürdürülebilirlik için iyi bir fikirdir. Senin için gelecek geliştirmeleri well designed 404 page kolayca uyum sağlamaları ErrorController kullanın. Ayrıca,yanıtınız 404 kodu olduğundan emin olun!

public class ErrorController : MyController
{
    #region Http404

    public ActionResult Http404(string url)
    {
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        var model = new NotFoundViewModel();
        // If the url is relative ('NotFound' route) then replace with Requested path
        model.RequestedUrl = Request.Url.OriginalString.Contains(url) & Request.Url.OriginalString != url ?
            Request.Url.OriginalString : url;
        // Dont get the user stuck in a 'retry loop' by
        // allowing the Referrer to be the same as the Request
        model.ReferrerUrl = Request.UrlReferrer != null &&
            Request.UrlReferrer.OriginalString != model.RequestedUrl ?
            Request.UrlReferrer.OriginalString : null;

        // TODO: insert ILogger here

        return View("NotFound", model);
    }
    public class NotFoundViewModel
    {
        public string RequestedUrl { get; set; }
        public string ReferrerUrl { get; set; }
    }

    #endregion
}

Adım 2: kolayca özel 404 eylem çağırmak ve HandleUnknownAction Tel böylece temel Denetleyici bir sınıfı Kullanın

ASP.NET MVC 404'ler yerlerde bir dizi de yakalanmış olması gerekir. İlk HandleUnknownAction.

InvokeHttp404 yöntemi ErrorController Http404 yeni eylem için yeniden yönlendirme için ortak bir yer oluşturur. DRY düşün!

public abstract class MyController : Controller
{
    #region Http404 handling

    protected override void HandleUnknownAction(string actionName)
    {
        // If controller is ErrorController dont 'nest' exceptions
        if (this.GetType() != typeof(ErrorController))
            this.InvokeHttp404(HttpContext);
    }

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

        return new EmptyResult();
    }

    #endregion
}

Adım 3: Denetleyicisi Fabrika Bağımlılık Enjeksiyon Kullanın ve 404 HttpExceptions Tel

Yani (StructureMap olmak zorunda değil) gibi

MVC1.0 örnek:

public class StructureMapControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(Type controllerType)
    {
        try
        {
            if (controllerType == null)
                return base.GetControllerInstance(controllerType);
        }
        catch (HttpException ex)
        {
            if (ex.GetHttpCode() == (int)HttpStatusCode.NotFound)
            {
                IController errorController = ObjectFactory.GetInstance<ErrorController>();
                ((ErrorController)errorController).InvokeHttp404(RequestContext.HttpContext);

                return errorController;
            }
            else
                throw ex;
        }

        return ObjectFactory.GetInstance(controllerType) as Controller;
    }
}

MVC2.0 örnek:

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        try
        {
            if (controllerType == null)
                return base.GetControllerInstance(requestContext, controllerType);
        }
        catch (HttpException ex)
        {
            if (ex.GetHttpCode() == 404)
            {
                IController errorController = ObjectFactory.GetInstance<ErrorController>();
                ((ErrorController)errorController).InvokeHttp404(requestContext.HttpContext);

                return errorController;
            }
            else
                throw ex;
        }

        return ObjectFactory.GetInstance(controllerType) as Controller;
    }

Daha kendi hataları onlar geldiği yerin yakınına yakalamak için sanırım. Bu Application_Error işleyicisi için yukarıdaki yüzden tercih ediyorum.

Bu 404 hataları yakalamak için ikinci ev.

Adım 4: Küresel NotFound için bir yol Ekleyin.uygulamanız ayrıştırılması başarısız olan adresi için asax

Bu yol Http404 bizim eylem için işaret etmelidir. url param yönlendirme motoru burada etki alanı bölümü sıyırma olduğu için göreli bir url olacak fark ettin mi? 1. Adımda tüm o koşullu url mantığı var.

        routes.MapRoute("NotFound", "{*url}", 
            new { controller = "Error", action = "Http404" });

Bu kendini çağırmak olmadığını MVC uygulaması 404 hataları yakalamak için üçüncü ve son yerdir. Eğer burada MVC sorunu kaçırmak için ASP.NET (Global.eşsiz yollar, Ne olursa.asax) ve gerçekten bu durumda sen bunu istemiyorsun.

Adım 5: son olarak, app bir şey bulamadıkları zaman 404 hataları çağırır

Kötü bir KİMLİĞİ benim Kredi denetleyicisi gönderildiğinde (MyController türetir) gibi

    //
    // GET: /Detail/ID

    public ActionResult Detail(int ID)
    {
        Loan loan = this._svc.GetLoans().WithID(ID);
        if (loan == null)
            return this.InvokeHttp404(HttpContext);
        else
            return View(loan);
    }

Tüm bu daha az kod ile daha az yerlerde bağladım olabilir ama bu çözüm, daha sürdürülebilir, daha fazla test edilebilir ve oldukça pragmatik olduğunu düşünüyorum eğer iyi olurdu.

Yorumunuz için teşekkürler şimdiye kadar. Daha fazla almak isterdim.

NOT: Bu önemli ölçüde orijinal cevabım ama yerine aynı - bu yeni bir cevap ekledim neden amacı düzenlenmiştir

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • bcbauer

    bcbauer

    7 ŞUBAT 2007
  • Epic Tutorials for iPhone, iPad and iOS

    Epic Tutoria

    18 EYLÜL 2011
  • TV and Lust

    TV and Lust

    26 HAZİRAN 2006