यदि मार्ग दिया गया है:
{FeedName} / {} ItemPermalink
ex: / ब्लॉग / हैलो-वर्ल्ड
यदि आइटम मौजूद नहीं है, तो मैं 404 वापस करना चाहता हूं। ASP.NET MVC में ऐसा करने का सही तरीका क्या है?
यदि मार्ग दिया गया है:
{FeedName} / {} ItemPermalink
ex: / ब्लॉग / हैलो-वर्ल्ड
यदि आइटम मौजूद नहीं है, तो मैं 404 वापस करना चाहता हूं। ASP.NET MVC में ऐसा करने का सही तरीका क्या है?
जवाबों:
कूल्हे से शूटिंग (चरवाहा कोडिंग; ;-)), मैं कुछ इस तरह का सुझाव दूंगा:
नियंत्रक:
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 :)
इस दृष्टिकोण का उपयोग करके आप फ्रेमवर्क मानकों का पालन करते हैं। वहां पहले से ही एक HttpUnauthorizedResult मौजूद है, इसलिए यह बस बाद में आपके कोड को बनाए रखने वाले किसी अन्य डेवलपर की आंखों में रूपरेखा का विस्तार करेगा (आप जानते हैं, वह साइको जो जानता है कि आप कहां रहते हैं)।
HttpUnauthorizedResult को कैसे प्राप्त किया जाता है यह देखने के लिए आप असेंबली में एक नज़र डालने के लिए उपयोग कर सकते हैं, क्योंकि मुझे नहीं पता कि क्या यह दृष्टिकोण कुछ भी याद करता है (यह बहुत सरल लगता है)।
मैंने अभी-अभी HttpUnauthorizedResult पर एक नज़र डालने के लिए रिफ्लेक्टर का उपयोग किया। लगता है कि वे 0x191 (401) की प्रतिक्रिया पर StatusCode सेट कर रहे हैं। हालाँकि यह 401 के लिए काम करता है, लेकिन नए मूल्य के रूप में 404 का उपयोग करके मुझे फ़ायरफ़ॉक्स में सिर्फ एक खाली पृष्ठ मिल रहा है। Internet Explorer डिफ़ॉल्ट 404 दिखाता है (ASP.NET संस्करण नहीं)। Webdeveloper टूलबार का उपयोग करके मैंने FF में हेडर का निरीक्षण किया, जो कि एक 404 Not Found प्रतिक्रिया को दर्शाता है। एफएफ में मुझे गलत तरीके से बताई गई कुछ चीजें हो सकती हैं।
यह किया जा रहा है ने कहा, मुझे लगता है कि जेफ के दृष्टिकोण KISS का एक अच्छा उदाहरण है। यदि आपको वास्तव में इस नमूने में वाचालता की आवश्यकता नहीं है, तो उसकी विधि ठीक काम करती है।
हम इसे पसंद करते हैं; इस कोड में पाया जाता हैBaseController
/// <summary>
/// returns our standard page not found view
/// </summary>
protected ViewResult PageNotFound()
{
Response.StatusCode = 404;
return View("PageNotFound");
}
ऐसा कहा जाता है
public ActionResult ShowUserDetails(int? id)
{
// make sure we have a valid ID
if (!id.HasValue) return PageNotFound();
HttpNotFoundResult एक महान पहला कदम है जो मैं उपयोग कर रहा हूं। एक HttpNotFoundResult लौटना अच्छा है। फिर सवाल यह है कि आगे क्या है?
मैंने HandleNotFoundAttribute नामक एक एक्शन फ़िल्टर बनाया, जो तब 404 एरर पेज दिखाता है। चूंकि यह एक दृश्य लौटाता है, आप प्रति नियंत्रक 404 दृश्य बना सकते हैं, या डिफ़ॉल्ट रूप से साझा किए गए 404 दृश्य का उपयोग कर सकते हैं। यह तब भी कहा जाएगा जब किसी नियंत्रक के पास निर्दिष्ट क्रिया मौजूद नहीं है, क्योंकि फ्रेमवर्क 404 की स्थिति कोड के साथ एक HttpException फेंकता है।
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 के रूप में, आप बस उपयोग कर सकते हैं HttpStatusCodeResult
।
HttpNotFoundResult
ActionFilter का उपयोग करना मुश्किल है क्योंकि जब भी हम एक त्रुटि फेंकते हैं तो फ़िल्टर को विशेषता में सेट करने की आवश्यकता होती है। क्या होगा अगर हम इसे सेट करना भूल जाते हैं? एक तरीका OnException
बेस कंट्रोलर पर आ रहा है। आपको एक BaseController
व्युत्पन्न से परिभाषित करने की आवश्यकता है Controller
और आपके सभी नियंत्रकों से प्राप्त होना चाहिएBaseController
। बेस कंट्रोलर होना सबसे अच्छा अभ्यास है।
ध्यान दें कि यदि Exception
प्रतिक्रिया स्थिति कोड 500 का उपयोग कर रहा है, तो हमें इसे 404 में नहीं मिला और अनधिकृत के लिए 401 में बदलना होगा। जैसे मैं ऊपर उल्लेख करता हूं, OnException
ओवरराइड्स का उपयोग करेंBaseController
फ़िल्टर विशेषता का उपयोग करने से बचने के का उपयोग करें।
नया MVC 3 भी ब्राउज़र के लिए एक खाली दृश्य लौटाकर अधिक परेशानी पैदा करता है। कुछ शोध के बाद सबसे अच्छा समाधान यहाँ मेरे जवाब पर आधारित है। एएसटी.नेट एमवीसी 3 में HttpNotFound () के लिए एक दृश्य कैसे वापस करें?
और अधिक विश्वास बनाने के लिए मैं इसे यहाँ प्रस्तुत करता हूँ:
कुछ अध्ययन के बाद। के लिए वैकल्पिक हल MVC 3 यहाँ सभी प्राप्त करने के लिए है HttpNotFoundResult
, HttpUnauthorizedResult
, HttpStatusCodeResult
वर्गों और लागू नई (यह अधिभावी) HttpNotFound
() में विधि BaseController
।
बेस कंट्रोलर का उपयोग करना सबसे अच्छा अभ्यास है ताकि आप सभी व्युत्पन्न नियंत्रकों पर 'नियंत्रण' रखें।
मैं नई HttpStatusCodeResult
श्रेणी बनाता हूं , न कि प्राप्त करने के लिए, ActionResult
लेकिन ViewResult
उस दृश्य या किसी भी संपत्ति View
को निर्दिष्ट करके जो आप चाहते ViewName
हैं। मैं HttpStatusCodeResult
सेट करने के लिए मूल का पालन करता हूं HttpContext.Response.StatusCode
और HttpContext.Response.StatusDescription
फिर base.ExecuteResult(context)
उपयुक्त दृश्य प्रदान करूंगा क्योंकि फिर से मैं प्राप्त करता हूं ViewResult
। बहुत सरल है? उम्मीद है कि इसे एमवीसी कोर में लागू किया जाएगा।
मेरा 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);
}
}
}
}
इस तरह से अपनी कार्रवाई में उपयोग करने के लिए:
public ActionResult Index()
{
// Some processing
if (...)
return HttpNotFound();
// Other processing
}
और _Layout.cshtml (मास्टर पेज की तरह)
<div class="content">
@if (ViewBag.Message != null)
{
<div class="inlineMsg"><p>@ViewBag.Message</p></div>
}
@RenderBody()
</div>
इसके अतिरिक्त आप कस्टम दृश्य का उपयोग कर सकते हैं जैसे Error.shtml
नया बना सकते हैं NotFound.cshtml
जैसे मैंने कोड में टिप्पणी की है और आप स्थिति विवरण और अन्य स्पष्टीकरण के लिए एक दृश्य मॉडल परिभाषित कर सकते हैं।