C# .NET8 веб-приложение: как перенаправить “плохие” URL на главную страницу?

Вопрос или проблема

Мы отказались от старого веб-сайта на ASP.NET, написанного на VB.NET. Вместо него мы заменили его простой “баннерной страницей”, написанной на C# на .NET 8.

Новое приложение имеет

  1. главную страницу и
  2. страницы для добавления, обновления и удаления “заявок на функции”.

Оно написано на C#, с использованием .NET 8. Оно размещено на IIS/Windows Server 2019.

Оригинальное приложение имело много различных URL. Я хотел убедиться, что пользователи всегда направляются на новую “главную” страницу, независимо от того, какой “старый” URL они пытаются использовать.

Я надеялся использовать “настройка ошибок” IIS; но это, похоже, не сработало (я пробовал множество вариантов).

Поэтому вместо этого я написал компонент промежуточного ПО для перенаправления по HTTP 404. Это, похоже, работает (я успешно перенаправляю на главную страницу, независимо от URL). Но я получаю эту ошибку:

Произошло необработанное исключение во время выполнения запроса. System.InvalidOperationException: Заголовки ответа не могут быть изменены, потому что ответ уже начат.

Код – RedirectPageNotFound.cs:

public class RedirectPageNotFound 
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RedirectPageNotFound> _logger;

    public RedirectPageNotFound(RequestDelegate next, ILogger<RedirectPageNotFound> logger) 
    {
        _next = next;
        _logger = logger;
    }

    public async Task Invoke(HttpContext context) 
    {
        await _next(context);

        if (context.Response.StatusCode == 404) 
        {
            _logger.LogInformation($"Обработка ошибки 404 для запроса {context.Request.Path}");
            context.Response.Redirect("/");
        } 
        else 
        {
            await _next(context);
        }
    }
}

Program.cs:

app.MapRazorPages();
app.MapControllers();
app.UseMiddleware<RedirectPageNotFound>();

Вопрос 1: Как я могу исправить System.InvalidOperationException?

Вопрос 2: Есть ли “более лучший” способ перенаправить “плохие URL” на мою “главную страницу”, так чтобы это вообще не делало HTTP перенаправление?

Я решил проблему, заставив мое промежуточное ПО проверять “context.EndPoint == null” вместо “context.Response.StatusCode == 404”:

public async Task Invoke(HttpContext context)
{
    if (context.GetEndpoint() == null)
    {
        string msg = string.Format("{0}\t{1}\t{2}",
            DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
            context.User.Identity.Name,
            context.Request.Path);
        using (FileStream fs = File.Open("user404.txt", FileMode.OpenOrCreate))
        {
            fs.Seek(0, SeekOrigin.End);
            using (StreamWriter sw = new StreamWriter(fs))
                sw.WriteLine(msg);
        }
        context.Response.Redirect("/");
    }
    else
    {
        await _next(context);
    }
}

.

Ответ или решение

Ответ на вопрос о маршрутизации "плохих" URL в C# .NET 8 веб-приложении

Проблема маршрутизации "плохих" URL к главной странице в приложении, созданном с использованием ASP.NET на платформе .NET 8, может быть решена несколькими способами. Ваша цель — перенаправить пользователей на главную страницу, если они пытаются обратиться к устаревшим или несуществующим URL. Давайте внимательно рассмотрим вашу ситуацию и предоставим детальные рекомендации по решению ваших вопросов.

Q1: Как исправить ошибку System.InvalidOperationException?

Ошибка, которую вы получаете, происходит из-за того, что вы пытаетесь изменить заголовки ответа после того, как они уже были отправлены клиенту. В вашем исходном коде вы вызываете метод _next(context), который обрабатывает следующий middleware в конвейере. После его завершения, если статус ответа уже был установлен (например, 404), вы не можете изменить его, так как заголовки уже отправлены.

Для решения этой проблемы вы уже нашли подход через проверку, есть ли конечная точка в контексте. Это правильный подход, так как вместо проверки статуса ответа вы просто проверяете, была ли указана конечная точка. Если конечная точка null, это означает, что маршрутизация не нашла подходящего контроллера или страницы, и следовательно, вам нужно перенаправить пользователя.

Ваш конечный исправленный код будет выглядеть так:

public async Task Invoke(HttpContext context)
{
    if (context.GetEndpoint() == null)
    {
        string msg = string.Format("{0}\t{1}\t{2}",
            DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
            context.User.Identity.Name,
            context.Request.Path);

        using (FileStream fs = File.Open("user404.txt", FileMode.OpenOrCreate))
        {
            fs.Seek(0, SeekOrigin.End);
            using (StreamWriter sw = new StreamWriter(fs))
                sw.WriteLine(msg);
        }

        context.Response.Redirect("/");
    }
    else
    {
        await _next(context);
    }
}

Этот код сначала проверяет, существует ли конечная точка, и, если ее нет, осуществляет перенаправление на главную страницу, избегая изменений заголовков после их отправки.

Q2: Есть ли более "лучший" способ перенаправления "плохих" URL без HTTP редиректа?

Да, существует еще один способ обработки "плохих" URL без необходимости использовать функцию перенаправления. Вместо этого, вы можете изменить ответ прямо в вашем middleware без перенаправления. Это можно сделать, установив содержимое ответа HTML и статус-код в 200 (или 404, если вы хотите оставить это в качестве индикации), что позволит вам контролировать то, что видит пользователь без изменения URL в адресной строке.

Вот пример, как это можно сделать:

public async Task Invoke(HttpContext context)
{
    if (context.GetEndpoint() == null)
    {
        context.Response.StatusCode = 200; // Устанавливаем статус 200
        context.Response.ContentType = "text/html";
        await context.Response.WriteAsync("<html><body><h1>Welcome to the Main Page!</h1></body></html>");
    }
    else
    {
        await _next(context);
    }
}

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

Заключение

В данном ответе мы рассмотрели, как правильно обрабатывать "плохие" URL в ASP.NET приложении на C# .NET 8, исправив возникшую проблему с изменением заголовков ответа, а также предложили альтернативный способ обработки запросов без перенаправления. Рекомендуется выбирать метод, который наилучшим образом соответствует требованиям вашего приложения и пользовательского опыта, который вы хотите предоставить пользователям.

Оцените материал
Добавить комментарий

Капча загружается...