Событие кнопки Asp.Net при обновлении запускается снова ??? GUID? - PullRequest
1 голос
/ 04 апреля 2009

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

Видимо ответ для каждого поста - создать GUID и проверить, чтобы убедиться, что GUID уникален? Я не совсем уверен, как это реализовать.

Означает ли это при обновлении, он попытается создать дублирующее сообщение с тем же GUID?

Как реализовать GUID в вашей базе данных? Или, если это не ответ, то что?

Спасибо!

Ответы [ 2 ]

1 голос
/ 04 апреля 2009

Вот элемент управления RefreshValidator, который я использую. Просто поместите его на свою страницу и проверьте Page.IsValid перед сохранением в базе данных. Вы можете добавить сообщение об ошибке, как и другие валидаторы, или перехватить событие Refreshed, если хотите сделать что-то особенное. Так как это Validator, GridViews и тому подобное уже заметят это - за исключением действий Delete или Cancel (да, у меня есть собственный GridView, который тоже это решает ...)

Код довольно прост - сохраните GUID в ControlState и копию в Session. При загрузке сравните 2. Если они не совпадают - тогда это обновление. Промойте, повторите и создайте новый GUID и начните заново.

''' <summary>
''' A validator control that detects if the page has been refreshed
''' </summary>
''' <remarks>If <see cref="SessionState.HttpSessionState" /> is not available or is reset, validator will return Valid</remarks>
Public Class RefreshValidator
   Inherits BaseValidator

   Private isRefreshed As Boolean

   Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
      MyBase.OnInit(e)
      Page.RegisterRequiresControlState(Me)
   End Sub

   Protected Overrides Function SaveControlState() As Object
      Dim obj As Object = MyBase.SaveControlState()
      Return New System.Web.UI.Pair(_pageHashValue, obj)
   End Function

   Protected Overrides Sub LoadControlState(ByVal savedState As Object)
      Dim pair As System.Web.UI.Pair = TryCast(savedState, System.Web.UI.Pair)
      If pair IsNot Nothing Then
         _pageHashValue = TryCast(pair.First, String)
         MyBase.LoadControlState(pair.Second)
      Else
         MyBase.LoadControlState(savedState)
      End If
   End Sub

   Private _pageHashValue As String

   Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
      MyBase.OnLoad(e)
      If HttpContext.Current Is Nothing OrElse HttpContext.Current.Session Is Nothing Then
          isRefreshed = False
          Return
      End If

      ' Get hash value from session
       Dim currHashValue As String = CType(HttpContext.Current.Session(Me.UniqueID & ":pageHashValue"), String)

       If _pageHashValue Is Nothing OrElse currHashValue Is Nothing Then
           ' No page hash value - must be first render
           ' No current hash value. Session reset?
           isRefreshed = False
       ElseIf currHashValue = _pageHashValue Then
           ' Everything OK
           isRefreshed = False
       Else
           ' Was refreshed
           isRefreshed = True
       End If

       ' Build new values for form hash
       Dim newHashValue As String = Guid.NewGuid().ToString()
       _pageHashValue = newHashValue
       HttpContext.Current.Session(Me.UniqueID & ":pageHashValue") = newHashValue
   End Sub

   Protected Overrides Function ControlPropertiesValid() As Boolean
       Return True
   End Function

   Protected Overrides Function EvaluateIsValid() As Boolean
       If isRefreshed Then OnRefreshed(EventArgs.Empty)
       Return Not isRefreshed
   End Function

   Protected Overridable Sub OnRefreshed(ByVal e As EventArgs)
       RaiseEvent Refreshed(Me, e)
   End Sub

   ''' <summary>
   ''' Fires when page is detected as a refresh
   ''' </summary>
   Public Event Refreshed As EventHandler
End Class
1 голос
/ 04 апреля 2009

Идея состоит в том, что вы создаете уникальный номер для формы, и когда форма публикуется, вы сохраняете этот уникальный номер в базе данных в записи, которую вы редактируете / создаете. Перед сохранением проверьте, не был ли этот номер уже использован, в этом случае это была форма, которая была восстановлена ​​путем обновления.

Если вы обновляете запись, вам нужно только проверить, была ли эта запись сохранена с тем же уникальным номером, но если вы добавляете новую запись, вы должны проверить, имеет ли какая-либо другая запись этот номер.

Guid - это хорошее число для использования, поскольку маловероятно, что вы получите дубликат. 31-битное случайное число, которое может генерировать класс Random, также вряд ли даст дубликаты, но 128-битный Guid делает его намного менее вероятным.

Вам не нужно создавать значение Guid в базе данных, просто используйте Guid.NewGuid() в коде, который инициализирует форму. Вы можете поместить Guid в скрытое поле в форме. В базе данных вам нужно только поле, которое может хранить значение Guid, либо тип данных Guid, если он доступен, либо просто текстовое поле, достаточно большое, чтобы вместить текстовое представление Guid.

Вы можете использовать метод ToString, чтобы получить строковое представление значения Guid (чтобы вы могли поместить его в форму). Использование id.ToString("N") дает наиболее компактный формат, то есть 32 шестнадцатеричных цифры без разделителей. Использование id.ToString("B") дает более узнаваемый формат "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}". Чтобы вернуть Guid из строки (любого формата), вы просто используете new Guid(str).

...