Как вернуть ответ 404 из приложения ASP.NET MVC? - PullRequest
3 голосов
/ 25 декабря 2009

У меня есть контроллер, который извлекает изображения из базы данных, изменяет их размеры, кэширует результат на диске и выдает изображение в виде Content() результата.

Недавно я добавил поддержку кода "Scrape-buster" на моем сайте. То есть я беру хэш уникального кода, прикрепленного к каждому изображению, плюс некоторую соль, и передаю первые несколько символов этого хеша пользователю для подтверждения во время поиска. Это позволяет мне не допустить, чтобы люди убирали каждое изображение с сайта. (Не входя в систему и не просматривая HTML, то есть.)

В любом случае, если код ScrapeBuster неверен, я хотел бы вернуть ошибку 404 с моего контроллера. Есть ли встроенный способ сделать это, или я смотрю на создание пользовательских ActionResult?

Ответы [ 5 ]

6 голосов
/ 25 декабря 2009

Самый простой (вероятно, не самый чистый) способ - бросить HttpException:

public static void Throw404()
{
    throw new HttpException(404, "The resource cannot be found");
}

Вы должны убедиться, что никто в стеке вызовов не перехватывает исключение. Таким образом, вывод будет выглядеть как обычный желтый экран смерти ASP.NET 404.

Более чистый способ - вернуть пользовательский результат:

public sealed class HttpNotFoundResult : ActionResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        context.HttpContext.Response.StatusCode = 404;
    }
}
5 голосов
/ 17 июня 2011

Почему бы просто не использовать встроенный HttpNotFoundResult?

return HttpNotFound ();

2 голосов
/ 25 декабря 2009

Вы можете отправить 403, вернув HttpUnauthorizedResult . Возможно, это более правильный ответ, поскольку URL-адрес действителен, но не содержит информации об авторизации. Если ваш сайт настроен правильно, будет также иметь преимущество перенаправления их на страницу входа.

1 голос
/ 25 декабря 2009
public class NotFoundViewResult : ViewResult
{
    public ViewResultNotFound()
    {
        ViewName = "NotFound";
    }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.TrySkipIisCustomErrors = true;
        context.HttpContext.Response.StatusCode = 404;

        base.ExecuteResult(context);
    }
}

И создать NotFound View в ~/Views/Shared папке

0 голосов
/ 26 декабря 2009

Спасибо всем, вот что я придумал из ваших ответов:

public static class HttpErrorResultHelper
{
    public static HttpErrorResult HttpError(this Controller controller, int statusCode)
    {
        return new HttpErrorResult
        {
            StatusCode = statusCode
        };
    }

    public static HttpErrorResult HttpError(this Controller controller, int statusCode, ActionResult chainedAction)
    {
        return new HttpErrorResult
        {
            StatusCode = statusCode,
            ChainedAction = chainedAction,
        };
    }
}

public sealed class HttpErrorResult : ActionResult
{
    public int StatusCode { get; set; }

    public ActionResult ChainedAction { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        context.HttpContext.Response.TrySkipIisCustomErrors = true;
        context.HttpContext.Response.StatusCode = this.StatusCode;

        if (this.ChainedAction != null)
        {
            ChainedAction.ExecuteResult(context);
        }
    }
}

То, что это делает, добавляет код состояния к началу ответа, в то же время позволяя отправлять фактический результат просмотра.

this.HttpError(404, this.View("NotFound"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...