Rota verilirse:
{FeedName} / {ItemPermalink}
örn: / Blog / Merhaba Dünya
Öğe yoksa, bir 404 döndürmek istiyorum. Bunu ASP.NET MVC'de yapmanın doğru yolu nedir?
Rota verilirse:
{FeedName} / {ItemPermalink}
örn: / Blog / Merhaba Dünya
Öğe yoksa, bir 404 döndürmek istiyorum. Bunu ASP.NET MVC'de yapmanın doğru yolu nedir?
Yanıtlar:
Kalçadan çekim (kovboy kodlaması ;-)), şöyle bir şey öneririm:
Denetleyici:
public class HomeController : Controller
{
public ActionResult Index()
{
return new HttpNotFoundResult("This doesn't exist");
}
}
HttpNotFoundResult:
using System;
using System.Net;
using System.Web;
using System.Web.Mvc;
namespace YourNamespaceHere
{
/// <summary>An implementation of <see cref="ActionResult" /> that throws an <see cref="HttpException" />.</summary>
public class HttpNotFoundResult : ActionResult
{
/// <summary>Initializes a new instance of <see cref="HttpNotFoundResult" /> with the specified <paramref name="message"/>.</summary>
/// <param name="message"></param>
public HttpNotFoundResult(String message)
{
this.Message = message;
}
/// <summary>Initializes a new instance of <see cref="HttpNotFoundResult" /> with an empty message.</summary>
public HttpNotFoundResult()
: this(String.Empty) { }
/// <summary>Gets or sets the message that will be passed to the thrown <see cref="HttpException" />.</summary>
public String Message { get; set; }
/// <summary>Overrides the base <see cref="ActionResult.ExecuteResult" /> functionality to throw an <see cref="HttpException" />.</summary>
public override void ExecuteResult(ControllerContext context)
{
throw new HttpException((Int32)HttpStatusCode.NotFound, this.Message);
}
}
}
// By Erik van Brakel, with edits from Daniel Schaffer :)
Bu yaklaşımı kullanarak çerçeve standartlarına uyarsınız. Orada zaten bir HttpUnauthorizedResult var, bu nedenle bu, daha sonra kodunuzu koruyan başka bir geliştiricinin gözünde çerçeveyi genişletecektir (bilirsiniz, nerede yaşadığınızı bilen psikopat).
HttpUnauthorizedResult'un nasıl elde edildiğini görmek için montaja bir göz atmak için reflektörü kullanabilirsiniz, çünkü bu yaklaşımın herhangi bir şeyi gözden kaçırıp kaçırmadığını bilmiyorum (neredeyse çok basit görünüyor).
Şu anda HttpUnauthorizedResult'a bir göz atmak için reflektör kullandım. Görünüşe göre 0x191 (401) yanıtında Durum Kodunu ayarlıyorlar. Bu 401 için işe yarasa da, yeni değer olarak 404'ü kullanarak Firefox'ta sadece boş bir sayfa görüyorum. Internet Explorer, varsayılan bir 404'ü gösterir (ASP.NET sürümünü değil). Web geliştiricisi araç çubuğunu kullanarak FF'deki 404 Not Found yanıtı gösteren başlıkları inceledim. FF'de yanlış yapılandırdığım bir şey olabilir.
Bununla birlikte, Jeff'in yaklaşımının KISS'in güzel bir örneği olduğunu düşünüyorum. Bu örnekteki ayrıntıya gerçekten ihtiyacınız yoksa, yöntemi de iyi çalışıyor.
Biz böyle yapıyoruz; bu kod şurada bulunurBaseController
/// <summary>
/// returns our standard page not found view
/// </summary>
protected ViewResult PageNotFound()
{
Response.StatusCode = 404;
return View("PageNotFound");
}
öyle aradı
public ActionResult ShowUserDetails(int? id)
{
// make sure we have a valid ID
if (!id.HasValue) return PageNotFound();
HttpNotFoundResult, kullandığım şey için harika bir ilk adımdır. Bir HttpNotFoundResult döndürmek iyidir. O zaman soru şu, sırada ne var?
HandleNotFoundAttribute adında bir 404 hata sayfası gösteren bir eylem filtresi oluşturdum. Bir görünüm döndürdüğü için, denetleyici başına özel bir 404 görünümü oluşturabilir veya varsayılan bir paylaşılan 404 görünümü kullanabilirsiniz. Bu, bir denetleyicide belirtilen eylem mevcut olmadığında bile çağrılır, çünkü çerçeve 404 durum kodlu bir HttpException oluşturur.
public class HandleNotFoundAttribute : ActionFilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
var httpException = filterContext.Exception.GetBaseException() as HttpException;
if (httpException != null && httpException.GetHttpCode() == (int)HttpStatusCode.NotFound)
{
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; // Prevents IIS from intercepting the error and displaying its own content.
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.StatusCode = (int) HttpStatusCode.NotFound;
filterContext.Result = new ViewResult
{
ViewName = "404",
ViewData = filterContext.Controller.ViewData,
TempData = filterContext.Controller.TempData
};
}
}
}
MVC3'ten itibaren sadece kullanabileceğinizi unutmayın HttpStatusCodeResult
.
HttpNotFoundResult
Kullanılması ActionFilter olduğunu korumak için sert bir hatayla filtre ihtiyacını atmak her özelliğinde ayarlanan olması sebebiyledir. Ya ayarlamayı unutursak? Bir yol, OnException
temel denetleyicide türetmektir . Bir BaseController
türetilmiş tanımlamanız gerekir Controller
ve tüm denetleyicilerinizin türetmesi gerekir BaseController
. Bir temel denetleyiciye sahip olmak en iyi uygulamadır.
Exception
Yanıt durum kodunu kullanmanın 500 olup olmadığına dikkat edin, bu nedenle, Bulunamadı için 404 ve Yetkisiz için 401 olarak değiştirmemiz gerekir. Yukarıda bahsettiğim gibi, filtre özelliğini kullanmaktan kaçınmak için OnException
geçersiz kılmaları kullanın BaseController
.
Yeni MVC 3, tarayıcıya boş bir görünüm döndürerek daha da zahmetli hale getiriyor. Biraz araştırmadan sonra en iyi çözüm buradaki cevabıma dayanmaktadır ASP.Net MVC 3'te HttpNotFound () için bir görünüm nasıl döndürülür?
Daha fazla rahatlık sağlamak için buraya yapıştırıyorum:
Biraz çalıştıktan sonra. İçin geçici çözüm MVC 3 Burada tüm türetmek olduğunu HttpNotFoundResult
, HttpUnauthorizedResult
, HttpStatusCodeResult
sınıfları ve uygulamak yeni (geçersiz kılma) HttpNotFound
içinde () yöntemini BaseController
.
Tüm türetilmiş Denetleyiciler üzerinde 'kontrol' sahibi olmanız için temel Denetleyiciyi kullanmak en iyi uygulamadır.
Ben yeni oluşturmak HttpStatusCodeResult
değil türediği, sınıf ActionResult
ancak gelen ViewResult
görünüm veya herhangi işlemek View
belirterek istediğiniz ViewName
özelliği. Aslini izleyin HttpStatusCodeResult
ayarlamak HttpContext.Response.StatusCode
ve HttpContext.Response.StatusDescription
ama sonra base.ExecuteResult(context)
tekrar ben kendisinden elde edildiğinden uygun görünümü oluşturur ViewResult
. Yeterince basit mi? Umarım bu MVC çekirdeğinde uygulanır.
Aşağıya bakın BaseController
:
using System.Web;
using System.Web.Mvc;
namespace YourNamespace.Controllers
{
public class BaseController : Controller
{
public BaseController()
{
ViewBag.MetaDescription = Settings.metaDescription;
ViewBag.MetaKeywords = Settings.metaKeywords;
}
protected new HttpNotFoundResult HttpNotFound(string statusDescription = null)
{
return new HttpNotFoundResult(statusDescription);
}
protected HttpUnauthorizedResult HttpUnauthorized(string statusDescription = null)
{
return new HttpUnauthorizedResult(statusDescription);
}
protected class HttpNotFoundResult : HttpStatusCodeResult
{
public HttpNotFoundResult() : this(null) { }
public HttpNotFoundResult(string statusDescription) : base(404, statusDescription) { }
}
protected class HttpUnauthorizedResult : HttpStatusCodeResult
{
public HttpUnauthorizedResult(string statusDescription) : base(401, statusDescription) { }
}
protected class HttpStatusCodeResult : ViewResult
{
public int StatusCode { get; private set; }
public string StatusDescription { get; private set; }
public HttpStatusCodeResult(int statusCode) : this(statusCode, null) { }
public HttpStatusCodeResult(int statusCode, string statusDescription)
{
this.StatusCode = statusCode;
this.StatusDescription = statusDescription;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
context.HttpContext.Response.StatusCode = this.StatusCode;
if (this.StatusDescription != null)
{
context.HttpContext.Response.StatusDescription = this.StatusDescription;
}
// 1. Uncomment this to use the existing Error.ascx / Error.cshtml to view as an error or
// 2. Uncomment this and change to any custom view and set the name here or simply
// 3. (Recommended) Let it commented and the ViewName will be the current controller view action and on your view (or layout view even better) show the @ViewBag.Message to produce an inline message that tell the Not Found or Unauthorized
//this.ViewName = "Error";
this.ViewBag.Message = context.HttpContext.Response.StatusDescription;
base.ExecuteResult(context);
}
}
}
}
Eyleminizde böyle kullanmak için:
public ActionResult Index()
{
// Some processing
if (...)
return HttpNotFound();
// Other processing
}
Ve _Layout.cshtml'de (ana sayfa gibi)
<div class="content">
@if (ViewBag.Message != null)
{
<div class="inlineMsg"><p>@ViewBag.Message</p></div>
}
@RenderBody()
</div>
Ek olarak, kodda yorumladığım gibi özel bir görünüm kullanabilir Error.shtml
veya yeni NotFound.cshtml
bir görünüm oluşturabilir ve durum açıklaması ve diğer açıklamalar için bir görünüm modeli tanımlayabilirsiniz.