programing

ASP.NET MVC 작업에서 HTTP 404 응답을 보내는 올바른 방법은 무엇입니까?

showcode 2023. 6. 14. 22:01
반응형

ASP.NET MVC 작업에서 HTTP 404 응답을 보내는 올바른 방법은 무엇입니까?

경로가 지정된 경우:

{FeedName}/{ItemPermalink}

ex: /Blog/Hello-World

만약 물건이 없다면 404를 반품하고 싶습니다.ASP.NET MVC에서 이 작업을 수행하는 올바른 방법은 무엇입니까?

엉덩이에서 촬영(카우보이 코딩;-), 저는 다음과 같은 것을 제안합니다.

컨트롤러:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return new HttpNotFoundResult("This doesn't exist");
    }
}

HttpNotFound 결과:

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)가 어떻게 달성되는지 확인할 수 있습니다. 이 접근 방식이 누락된 것이 있는지 알 수 없기 때문입니다(거의 단순한 것 같습니다).


방금 리플렉터를 사용하여 HttpUnauthorizedResult를 살펴보았습니다.응답에 대한 상태 코드를 0x191(401)로 설정하는 것 같습니다.이것은 401에 대해 작동하지만 404를 새로운 값으로 사용하면 Firefox에서 빈 페이지만 표시되는 것 같습니다.Internet Explorer는 기본 404를 표시하지만 ASP.NET 버전은 표시하지 않습니다.웹 개발자 도구 모음을 사용하여 FF의 헤더를 검사했는데, 404 Not Found 응답을 표시합니다.단순히 FF에서 잘못 구성한 것일 수 있습니다.


이런 말이 나온 김에 제프의 접근법은 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();
throw new HttpException(404, "Are you sure you're in the right place?");

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.

오류가 발생할 때마다 특성에 필터를 설정해야 하므로 ActionFilter를 사용하는 것은 유지하기 어렵습니다.설정하는 것을 잊으면 어떻게 합니까?하나의 방법은 도출하는 것입니다.OnException기본 컨트롤러에 있습니다.은 정야해합다니를 해야 합니다.BaseController에서파된에서 Controller그리고 모든 컨트롤러는 다음과 같은 이점을 제공해야 합니다.BaseController기본 컨트롤러를 사용하는 것이 가장 좋습니다.

사용하는 경우 참고Exception응답 상태 코드는 500이므로, 찾을 수 없음은 404, 무단은 401로 변경해야 합니다.위에처럼, 서언것처럼한급다니, 사합용을에위다니를 합니다.OnException에 대한 오버라이드.BaseController필터 특성을 사용하지 않도록 합니다.

새로운 MVC 3는 또한 브라우저에 빈 보기를 반환함으로써 더 많은 문제를 일으킵니다.몇 가지 조사 후 가장 좋은 해결책은 ASP.Net MVC 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이것이 MVC 코어에서 구현되기를 바랍니다.

내 것 보기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>

또한다음과같사정보의사수있다습니용할기를용자은▁like▁view다와 같은 정의 보기를 할 수 .Error.shtml 새 또는새만을 합니다.NotFound.cshtml코드에서 언급한 것처럼 상태 설명 및 기타 설명에 대한 뷰 모델을 정의할 수 있습니다.

언급URL : https://stackoverflow.com/questions/499817/what-is-the-proper-way-to-send-an-http-404-response-from-an-asp-net-mvc-action

반응형