Search code examples
model-view-controllereditingduplication

MVC DB Duplication check, trouble when editing


I had to do some kind of duplication check of data when creating an entry (lets say username). I did it by this. (It's in VB, but don't bother)

In controller:

Function CheckForDuplication(ByVal UserName As String) As JsonResult


    If db.Users.Count(Function(x) x.Username.ToLower() = UserName.ToLower()) > 0 Then

        Return Json(False, JsonRequestBehavior.AllowGet)

    Else

        Return Json(True, JsonRequestBehavior.AllowGet)
    End If


End Function

and in model:

<Remote("CheckForDuplication", "User", HttpMethod:="POST", ErrorMessage:="username not available")>
Public Property Username As String

and using standard JS validation libraries in view.

It works real fine... when creating. The trouble is that when editing you can't save back the same username because it's forbidden be the client-side validation.. as it already exist in DB. How can the validation be over-passed for current 'username' but remain for others. Or it should be redone with custom JS and [remote] removed from model. Thank you


Solution

  • I found out a solution to my problem by myself. I'll post it if someone else needs it. It's not very pretty one but works fine. What I've done is that when I call the View to edit I pass a TempData["name"]. And when edit the field and JS calls the CheckForDuplication method I can read the content of TempData["name"] (TempData seems to 'survive' the transition from View back to controller method, unlike ViewBag and ViewData) And when the check for duplication is made whit TempData["name"] in mind. The problem is that in that first check TempData is wiped clean (lifespan seems to be one request long) so.... I also pass a ViewBag.name to the View and made a JS script which calls a method that re set TempData["name"] with the value of ViewBag.name (since TempData["name"] can be set only server side)

    Controller

    Public Function Edit(UserId As Integer) As ViewResult
        Dim user As User= context.User.Find(UserId)
    
        ViewBag.UserName = user.UserName
        TempData("UserName") = user.UserName
    
        Return View(user)
    End Function
    

    '''''''''''

    Function CheckForDuplicationUserName(ByVal UserName As String) As JsonResult
    
    
    
        If context.User.Count(Function(x) x.UserName.ToLower() = UserName.ToLower()) = 0 Then
            Return Json(True, JsonRequestBehavior.AllowGet)
    
        ElseIf TempData("UserName") Is Nothing Then
            Return Json(False, JsonRequestBehavior.AllowGet)
    
        ElseIf TempData("UserName").ToString().ToLower() = UserName.ToLower() Then
            Return Json(True, JsonRequestBehavior.AllowGet)
        Else : Return Json(False, JsonRequestBehavior.AllowGet)
    
        End If
    End Function
    

    ''''''''''

        <HttpPost>
    <AllowAnonymous>
    Function SetTempData(ByVal name As String)
    
        TempData("UserName") = name
    
    End Function
    

    View

    <script type="text/javascript">
    
    function ResetTempData() {
        var url = "/User/SetTempData";
        var TDname = "@ViewBag.UserName"
        $.post(url, { name: TDname});
    };
    
    $('#UserName').change(ResetTempData);
    </script>
    

    Looks very strange but works. I hope it comes handy to someone