views:

27

answers:

0

I use a post-redirect-get (PRG) pattern to save an entity in ASP.Net MVC 2. The controller methods are 'Save' (inserts or updates database) and 'Edit' (retrieves user input). In 'Save', I do modification check before saving by checking a 'version' column of the entity. If someone else has modified the entity, the 'version' column will not match and I will send error message to the user.

To maintain error messages, I use ModelState.Merge in 'Edit' method. The problem with this mechanism is that the user input is maintained and the user doesn't see the modification made by the other user. I avoid this problem by clearing ModelState before adding the concurrency clash message.

But I feel this solution is not optimal. How would you handle concurrency clash in ASP.Net MVC?

Here is the Edit method:

    Public Function Edit() As ActionResult
        Dim theevent As AEvents

        If TempData("ModelState") IsNot Nothing And Not ModelState.Equals(TempData("ModelState")) Then
            ModelState.Merge(CType(TempData("ModelState"), ModelStateDictionary))
        End If

        If RouteData.Values.ContainsKey("id") Then
            theevent = NHibGet.EventWithPricingsByCode(RouteData.Values("id"))
        Else
            theevent = New AEvents
        End If

        Dim InputTemplate As New EventEdit With {.EventDate = theevent.EventDate, .EventName = theevent.EventName, .IsActive = theevent.IsActive}
        If theevent.Template IsNot Nothing Then
            InputTemplate.TemplateID = theevent.Template.ID
        End If

        Dim templates As IList(Of SeatTemplates) = NHibGet.TemplatesActive
        ViewData("templates") = templates

        ViewData("eventcode") = theevent.Code
        ViewData("editversion") = theevent.Version

        Return View(InputTemplate)
    End Function

And the code for 'Save' is like this:

    Public Function Save(ByVal id As Integer, ByVal UserData As EventEdit, ByVal EditVersion As Integer) As ActionResult
        Dim theevent As AEvents
        If id = 0 Then
            theevent = New AEvents
        Else
            theevent = NHibGet.EventByCode(id)
        End If

        If theevent.Version <> EditVersion Then
            ModelState.Clear()
            ModelState.AddModelError("", "The event is modified by someone else")
            Return RedirectToAction("Edit", New With {.id = id})
        End If

        If Not ModelState.IsValid Then
            TempData("ModelState") = ModelState
            Return RedirectToAction("Edit", New With {.id = id})
        End If

        theevent.EventDate = UserData.EventDate
        theevent.EventName = UserData.EventName
        theevent.IsActive = UserData.IsActive
        theevent.Template = MvcApplication.CurrentSession.Load(Of SeatTemplates)(UserData.TemplateID)

        Using trans As NHibernate.ITransaction = MvcApplication.CurrentSession.BeginTransaction
            MvcApplication.CurrentSession.SaveOrUpdate(theevent)

            Try
                trans.Commit()
            Catch ex As NHibernate.ADOException
                trans.Rollback()
                Throw ex
            End Try
        End Using

        Return RedirectToAction("Edit", New With {.id = theevent.Code})
    End Function