Validators & ICallbackEventHandler

Discussion in 'ASP .Net Web Controls' started by Nathan Sokalski, Mar 25, 2008.

  1. I have been attempting to create a Validator that checks whether a value
    entered into a TextBox is unique from the values in a specified field in a
    database. Doing this validation is quite simple when using postbacks, but I
    would like to do it using client callbacks by implementing the
    ICallbackEventHandler interface (if you want to do postbacks, just use the
    CustomValidator). Here is the code I have written for my first attempt:


    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    Imports System.Data.OleDb
    Public Class UVVOleDb : Inherits BaseValidator : Implements
    ICallbackEventHandler
    Dim connstring As String = ""
    Dim connstringkey As String = ""
    Dim dbfield As String = ""
    Dim dbtable As String = ""
    Dim dbtype As DBTypes = DBTypes.Character

    Public Property ConnectionString() As String
    Get
    Return Me.connstring
    End Get
    Set(ByVal value As String)
    If Me.connstringkey = "" Then Me.connstring = value
    End Set
    End Property
    Public Property ConnectionStringKey() As String
    Get
    Return Me.connstringkey
    End Get
    Set(ByVal value As String)
    Me.connstring =
    System.Configuration.ConfigurationManager.AppSettings(value)
    Me.connstringkey = value
    End Set
    End Property
    Public Property FieldName() As String
    Get
    Return Me.dbfield
    End Get
    Set(ByVal value As String)
    Me.dbfield = value
    End Set
    End Property
    Public Property TableName() As String
    Get
    Return Me.dbtable
    End Get
    Set(ByVal value As String)
    Me.dbtable = value
    End Set
    End Property
    Public Property FieldType() As DBTypes
    Get
    Return Me.dbtype
    End Get
    Set(ByVal value As DBTypes)
    Me.dbtype = value
    End Set
    End Property

    Protected Overrides Function EvaluateIsValid() As Boolean
    Dim validationvalue As String =
    Me.GetControlValidationValue(Me.ControlToValidate)
    Select Case Me.dbtype
    Case DBTypes.Character
    Return Me.DoValidation("'" & validationvalue.Replace("'",
    "''") & "'")
    Case DBTypes.DateTime
    Return Me.DoValidation(String.Concat("#",
    CDate(validationvalue).ToShortDateString(), "#"))
    Case DBTypes.NoQuotes
    Return Me.DoValidation(validationvalue)
    End Select
    End Function

    Private Function DoValidation(ByVal currvalue As String) As Boolean
    Dim myconnection As New OleDbConnection(Me.connstring)
    Dim cmdunique As New OleDbCommand(String.Format("SELECT {0} FROM {1}
    WHERE {0}={2}", Me.dbfield, Me.dbtable, currvalue), myconnection)
    Dim uniquereader As OleDbDataReader
    myconnection.Open()
    uniquereader = cmdunique.ExecuteReader()
    Return Not uniquereader.HasRows()
    myconnection.Close()
    End Function

    Private Sub Page_PreRender(ByVal sender As Object, ByVal e As
    System.EventArgs) Handles Me.PreRender
    If Not
    Me.Page.ClientScript.IsClientScriptBlockRegistered(String.Concat(Me.ClientID,
    "UVVevalfunc")) Then
    Me.Page.ClientScript.RegisterClientScriptBlock(Me.GetType(),
    String.Concat(Me.ClientID, "UVVevalfunc"), String.Format("function
    {0}UVVevalfunc(val){{{1};return tempisvalid;tempvalid=null;}}", Me.ClientID,
    Me.Page.ClientScript.GetCallbackEventReference(Me,
    "document.getElementById(val.controltovalidate).value", "SetIsUnique",
    Nothing)), True)
    If Not
    Me.Page.ClientScript.IsClientScriptBlockRegistered("SetIsUnique") Then
    Me.Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "SetIsUnique",
    "function SetIsUnique(isvalid){tempisvalid=isvalid;return true;}", True)
    End Sub

    Public Function GetCallbackResult() As String Implements
    System.Web.UI.ICallbackEventHandler.GetCallbackResult
    Return CStr(IIf(Me.IsValid, "1", "0"))
    End Function

    Public Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements
    System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
    Me.IsValid = Me.EvaluateIsValid()
    End Sub

    Protected Overrides Sub AddAttributesToRender(ByVal writer As
    System.Web.UI.HtmlTextWriter)
    MyBase.AddAttributesToRender(writer)
    writer.AddAttribute("evaluationfunction", String.Concat(Me.ClientID,
    "UVVevalfunc"))
    End Sub
    End Class

    Public Enum DBTypes As Byte
    Character 'Include single quotes, used for text types such as VARCHAR,
    CHAR, etc.
    DateTime 'Use the appropriate format for DATETIME for the selected
    provider
    NoQuotes 'Do not modify, used for numeric and other types that do not
    require formatting
    End Enum


    The validator gives the correct validation, but it always does a postback,
    which pretty much removes the purpose of implementing ICallbackEventHandler.
    I believe the reason for the problem is that when the validation is
    triggered on the client side, the function specified by the validator's
    evaluationfunction is called. However, the basic procedure for the callback
    is to initiate the callback using a JavaScript statement, which I placed
    inside the function specified by evaluationfunction. When returning from the
    callback, another JavaScript function is called and is passed the result of
    the callback. I had this function assign the result to a variable. The
    evaluationfunction function then, supposedly, returns that variable to
    complete the process. However, because this is not working, I have a theory
    that because the client callback occurs while inside the evaluationfunction,
    the value that it is supposed to return is not getting returned, causing
    some sort of problem during the attempt to do client-side validation that
    forces the page to use a postback. I may not have explained this perfectly,
    but if you look at my code, you should be able to figure out what I was
    attempting to do. Any ideas for a solution or workaround? Thanks.
    --
    Nathan Sokalski

    http://www.nathansokalski.com/
    Nathan Sokalski, Mar 25, 2008
    #1
    1. Advertising

  2. Nathan Sokalski

    bruce barker Guest

    your approach will not work. ajax callbacks (which the
    icallbackeventhander uses) are async, while the call to your validator
    is synchronous. the valididator is called during the submit event, and
    must return true or false on whether to cancel the postback. if your
    validator makes an ajax call, the response event can not be fired until
    after the original postback has started or been canceled.

    you could fire an ajax event on lost focus, and update a flag the
    validator looked at. if the postback happens before the ajax call
    completes, then allow the postback and validate on the server.

    -- bruce (sqlwork.com)

    Nathan Sokalski wrote:
    > I have been attempting to create a Validator that checks whether a value
    > entered into a TextBox is unique from the values in a specified field in a
    > database. Doing this validation is quite simple when using postbacks, but I
    > would like to do it using client callbacks by implementing the
    > ICallbackEventHandler interface (if you want to do postbacks, just use the
    > CustomValidator). Here is the code I have written for my first attempt:
    >
    >
    > Imports System.Web.UI
    > Imports System.Web.UI.WebControls
    > Imports System.Data.OleDb
    > Public Class UVVOleDb : Inherits BaseValidator : Implements
    > ICallbackEventHandler
    > Dim connstring As String = ""
    > Dim connstringkey As String = ""
    > Dim dbfield As String = ""
    > Dim dbtable As String = ""
    > Dim dbtype As DBTypes = DBTypes.Character
    >
    > Public Property ConnectionString() As String
    > Get
    > Return Me.connstring
    > End Get
    > Set(ByVal value As String)
    > If Me.connstringkey = "" Then Me.connstring = value
    > End Set
    > End Property
    > Public Property ConnectionStringKey() As String
    > Get
    > Return Me.connstringkey
    > End Get
    > Set(ByVal value As String)
    > Me.connstring =
    > System.Configuration.ConfigurationManager.AppSettings(value)
    > Me.connstringkey = value
    > End Set
    > End Property
    > Public Property FieldName() As String
    > Get
    > Return Me.dbfield
    > End Get
    > Set(ByVal value As String)
    > Me.dbfield = value
    > End Set
    > End Property
    > Public Property TableName() As String
    > Get
    > Return Me.dbtable
    > End Get
    > Set(ByVal value As String)
    > Me.dbtable = value
    > End Set
    > End Property
    > Public Property FieldType() As DBTypes
    > Get
    > Return Me.dbtype
    > End Get
    > Set(ByVal value As DBTypes)
    > Me.dbtype = value
    > End Set
    > End Property
    >
    > Protected Overrides Function EvaluateIsValid() As Boolean
    > Dim validationvalue As String =
    > Me.GetControlValidationValue(Me.ControlToValidate)
    > Select Case Me.dbtype
    > Case DBTypes.Character
    > Return Me.DoValidation("'" & validationvalue.Replace("'",
    > "''") & "'")
    > Case DBTypes.DateTime
    > Return Me.DoValidation(String.Concat("#",
    > CDate(validationvalue).ToShortDateString(), "#"))
    > Case DBTypes.NoQuotes
    > Return Me.DoValidation(validationvalue)
    > End Select
    > End Function
    >
    > Private Function DoValidation(ByVal currvalue As String) As Boolean
    > Dim myconnection As New OleDbConnection(Me.connstring)
    > Dim cmdunique As New OleDbCommand(String.Format("SELECT {0} FROM {1}
    > WHERE {0}={2}", Me.dbfield, Me.dbtable, currvalue), myconnection)
    > Dim uniquereader As OleDbDataReader
    > myconnection.Open()
    > uniquereader = cmdunique.ExecuteReader()
    > Return Not uniquereader.HasRows()
    > myconnection.Close()
    > End Function
    >
    > Private Sub Page_PreRender(ByVal sender As Object, ByVal e As
    > System.EventArgs) Handles Me.PreRender
    > If Not
    > Me.Page.ClientScript.IsClientScriptBlockRegistered(String.Concat(Me.ClientID,
    > "UVVevalfunc")) Then
    > Me.Page.ClientScript.RegisterClientScriptBlock(Me.GetType(),
    > String.Concat(Me.ClientID, "UVVevalfunc"), String.Format("function
    > {0}UVVevalfunc(val){{{1};return tempisvalid;tempvalid=null;}}", Me.ClientID,
    > Me.Page.ClientScript.GetCallbackEventReference(Me,
    > "document.getElementById(val.controltovalidate).value", "SetIsUnique",
    > Nothing)), True)
    > If Not
    > Me.Page.ClientScript.IsClientScriptBlockRegistered("SetIsUnique") Then
    > Me.Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "SetIsUnique",
    > "function SetIsUnique(isvalid){tempisvalid=isvalid;return true;}", True)
    > End Sub
    >
    > Public Function GetCallbackResult() As String Implements
    > System.Web.UI.ICallbackEventHandler.GetCallbackResult
    > Return CStr(IIf(Me.IsValid, "1", "0"))
    > End Function
    >
    > Public Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements
    > System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
    > Me.IsValid = Me.EvaluateIsValid()
    > End Sub
    >
    > Protected Overrides Sub AddAttributesToRender(ByVal writer As
    > System.Web.UI.HtmlTextWriter)
    > MyBase.AddAttributesToRender(writer)
    > writer.AddAttribute("evaluationfunction", String.Concat(Me.ClientID,
    > "UVVevalfunc"))
    > End Sub
    > End Class
    >
    > Public Enum DBTypes As Byte
    > Character 'Include single quotes, used for text types such as VARCHAR,
    > CHAR, etc.
    > DateTime 'Use the appropriate format for DATETIME for the selected
    > provider
    > NoQuotes 'Do not modify, used for numeric and other types that do not
    > require formatting
    > End Enum
    >
    >
    > The validator gives the correct validation, but it always does a postback,
    > which pretty much removes the purpose of implementing ICallbackEventHandler.
    > I believe the reason for the problem is that when the validation is
    > triggered on the client side, the function specified by the validator's
    > evaluationfunction is called. However, the basic procedure for the callback
    > is to initiate the callback using a JavaScript statement, which I placed
    > inside the function specified by evaluationfunction. When returning from the
    > callback, another JavaScript function is called and is passed the result of
    > the callback. I had this function assign the result to a variable. The
    > evaluationfunction function then, supposedly, returns that variable to
    > complete the process. However, because this is not working, I have a theory
    > that because the client callback occurs while inside the evaluationfunction,
    > the value that it is supposed to return is not getting returned, causing
    > some sort of problem during the attempt to do client-side validation that
    > forces the page to use a postback. I may not have explained this perfectly,
    > but if you look at my code, you should be able to figure out what I was
    > attempting to do. Any ideas for a solution or workaround? Thanks.
    bruce barker, Mar 26, 2008
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ratman
    Replies:
    0
    Views:
    649
    Ratman
    Sep 14, 2004
  2. begemot

    ICallbackEventHandler and Mozilla

    begemot, Jun 21, 2005, in forum: ASP .Net
    Replies:
    3
    Views:
    1,237
    begemot
    Jun 22, 2005
  3. JimGreen

    ICallbackEventHandler Q????

    JimGreen, Oct 14, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    415
  4. Nathan Sokalski

    Validators & ICallbackEventHandler

    Nathan Sokalski, Mar 25, 2008, in forum: ASP .Net
    Replies:
    1
    Views:
    510
    bruce barker
    Mar 26, 2008
  5. Nathan Sokalski

    Validators & ICallbackEventHandler

    Nathan Sokalski, Mar 25, 2008, in forum: ASP .Net Building Controls
    Replies:
    1
    Views:
    785
    bruce barker
    Mar 26, 2008
Loading...

Share This Page