Как я могу игнорировать http-запрос без очистки браузера? - PullRequest
1 голос
/ 24 марта 2010

Чтобы предотвратить повторяющиеся запросы (то есть нажатие клавиши F5 сразу после нажатия кнопки), я настроил базовый класс своей страницы, чтобы игнорировать запрос, если он обнаружен как дубликат.

Когда я говорю «игнорировать», я имею в виду Response.End ()

Теперь я думал, что видел эту работу раньше, где есть проблема, я просто Response.End () и страница пользователей просто ничего не делает. Я не знаю точных обстоятельств, в которых это сработало, но я не могу повторить это сейчас.

Теперь, когда я вызываю Response.End (), я просто получаю пустой браузер. Более конкретно, я получаю этот HTML.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=utf-8"></HEAD>
<BODY></BODY></HTML>

Я установил следующее тестовое приложение, чтобы убедиться, что проблема не в другом месте моего приложения. Вот оно:

Добавьте следующее в форму aspx

<asp:Label ID="lbl" Text="0" runat="server" /><br />
<asp:Button ID="btnAdd1" Text="Add 1" runat="server" /><br />
<asp:Button ID="btnAdd2" Text="Add 2" runat="server" /><br />
<asp:Button ID="btnAdd3" Text="Add 3" runat="server" /><br />

А вот код файла

using System;

namespace TestDupRequestCancellation
{
 public partial class _Default : System.Web.UI.Page
 {
  protected void Page_Init(object sender, EventArgs e)
  {
   btnAdd1.Click += btnAdd1_Click;
   btnAdd2.Click += btnAdd2_Click;
   btnAdd3.Click += btnAdd3_Click;
  }

  protected void Page_Load(object sender, EventArgs e)
  {
   if (!IsPostBack)
    CurrentValue = 0;
   else if (Int32.Parse(lbl.Text) != CurrentValue)
    Response.End();
  }

  protected void Page_PreRender(object sender, EventArgs e)
  {
   lbl.Text = CurrentValue.ToString();
  }

  protected int CurrentValue
  {
   get
   {
    return Int32.Parse(Session["CurrentValue"].ToString());
   }
   set
   {
    Session["CurrentValue"] = value.ToString();
   }
  }

  void btnAdd3_Click(object sender, EventArgs e)
  {
   CurrentValue += 3;
  }

  void btnAdd2_Click(object sender, EventArgs e)
  {
   CurrentValue += 2;
  }

  void btnAdd1_Click(object sender, EventArgs e)
  {
   CurrentValue += 1;
  }
 }
}

Когда вы загружаете страницу, нажатие любой кнопки делает то, что ожидается, но если вы нажмете F5 в любое время после нажатия одной из кнопок, она обнаружит ее как дублирующий запрос и вызовет Response.End (), который быстро завершится задание. Что оставляет пользователю пустой браузер.

Можно ли в любом случае оставить пользователя со страницей такой, какой она была, чтобы он мог просто нажать кнопку?

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

РЕДАКТИРОВАТЬ: Еще одно изменение, которое позволит мне достичь тех же результатов, будет отключить все мои обработчики событий. Это возможно?

Ответы [ 3 ]

1 голос
/ 25 марта 2010

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

попробуйте это:

using System;
using System.Web.UI.WebControls;

namespace TestDupRequestCancellation
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            btnAdd1.Click += btnAdd1_Click;
            btnAdd2.Click += btnAdd2_Click;
            btnAdd3.Click += btnAdd3_Click;
            AddFirstPostbackValidator();
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
                CurrentValue = 0;
        }

        protected void Page_PreRender(object sender, EventArgs e)
        {
            lbl.Text = CurrentValue.ToString();
        }

        protected int CurrentValue
        {
            get
            {
                return Int32.Parse(Session["CurrentValue"].ToString());
            }
            set
            {
                Session["CurrentValue"] = value.ToString();
            }
        }

        private void AddFirstPostbackValidator()
        {
            CustomValidator val = new CustomValidator();
            val.ID = "DuplicatePostbackValidator";
            val.ErrorMessage = "Browser refresh detected. Command ignored.";
            val.ServerValidate += val_ServerValidate;
            Validators.Add(val);
            form1.Controls.AddAt(form1.Controls.IndexOf(lbl) + 1, val); // user feedback
        }

        void val_ServerValidate(object source, ServerValidateEventArgs args)
        {
            args.IsValid = Int32.Parse(lbl.Text) == CurrentValue;
        }

        void btnAdd3_Click(object sender, EventArgs e)
        {
            if (!IsValid) 
                return;
            CurrentValue += 3;
        }

        void btnAdd2_Click(object sender, EventArgs e)
        {
            if (!IsValid)
                return;
            CurrentValue += 2;
        }

        void btnAdd1_Click(object sender, EventArgs e)
        {
            if (!IsValid)
                return;
            CurrentValue += 1;
        }
    }
}
0 голосов
/ 25 марта 2010

Посмотрите, отправляет ли код ответа HTTP 204 Нет содержимого делает то, что вы хотите.

0 голосов
/ 24 марта 2010

Не заставляйте ответ заканчиваться. Позвольте этому закончиться изящно (провалиться), не проходя вашу "основную" логику для законных запросов. Если это окажется слишком много работы, то ваш код, вероятно, необходимо реорганизовать. Или, ленивый выход, вы можете установить глобальное логическое значение, указывающее на действительность запросов (заданное в вашей Page_Load), а затем проверять его в остальной части кода, если необходимо.

EDIT

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...