locked
How to validate a field without posting the form? RRS feed

  • Question

  • User1546138644 posted

    I would like to check some data entry on a form as soon as the user has entered the data (which will involve a database lookup) without having the user fill out the whole form only to find at the end it was a waste of time.

    I assume I will need Javascript for this, something I have zero experience with (but no problems starting to learn). Can anyone recommend any good resources for solving this specific problem (as I need to get to a solution faster than learning a whole new language before I can start thinking about the solution for this issue)?

    Must be a common problem right?

    Friday, July 12, 2013 10:43 AM

Answers

  • User-821857111 posted

    I would recommend using jQuery for your AJAX. Here's an old article I wrote that shows how to do this with a web forms web method (asmx).

    http://www.mikesdotnetting.com/Article/99/Preventing-duplicate-User-Names-with-ASP.NET-and-jQuery

    You can replace the WebMethod code for something that uses the database helper and put it into a .cshtml file instead. Here's a simple example that tests for "Pete". Call this CheckUser.cshtml:

     

    @{
        var reader = new StreamReader(Request.InputStream);
        var json = Json.Decode(reader.ReadToEnd());
        if(json.name == "Pete"){
            Json.Write(true, Response.Output);
        }
        else{
            Json.Write(false, Response.Output);
        }
    }

    And here's a form that makes use of it:

    @{
        
    }
    
    <!DOCTYPE html>
    
    <html lang="en">
        <head>
            <meta charset="utf-8" />
            <title></title>
            <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script> 
            <script type="text/javascript"> 
              $(function() {
                $("#Name").change(checkUser);
              });
     
              function checkUser() {
                $.ajax({
                  type: "POST",
                  url: "CheckUser/",
                  data: "{name: '" + $('#Name').val() + "'}",
                  contentType: "application/json; charset=utf-8",
                  dataType: "json",
                  success: function(data) {
                    $("#duplicate").empty();
                    if (data != "0") {
                      $("#duplicate").html(' That name has already been taken');
                    }
                  }
                });
              }
     
            </script> 
        </head>
        <body>
            <form method="post">
            <div>Name: </div>
            <div>@Html.TextBox("Name") <span id="duplicate"></span></div>
            </form>
        </body>
    </html>
    



    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, July 15, 2013 11:41 AM
  • User-821857111 posted

    @oldname needs to go in quotes:

    data: "{name: '" + $('#bandName').val() + "', oldName: '@oldBandName' }",
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, July 18, 2013 12:31 AM

All replies

  • User1648350404 posted

    the ASP.NET MVC framework has included a mechnism called Unobtrusive Client Validation. This is a kind of bridge between server-side validators - applied using DataAnnotation attributes on model properties, and the popular jQuery Validate plugin.refer following:

    http://www.mikesdotnetting.com/Article/191/Validation-In-Razor-Web-Pages-2

    Friday, July 12, 2013 11:10 AM
  • User1546138644 posted

    As far as I can see article above provides client side validation. I need to compare the value that the user enters to a value in the database. In essence I need to warn the user that the primary data they have entered already exists in the database (is in use by someone else in fact) before they add lots of fields of information and then submit the record. By definition this must go back to the server to do the database checking surely?

     

    Friday, July 12, 2013 2:39 PM
  • User895691971 posted

    No brother, you are not just connecting a page to some Universal variable, but you are connecting the page to the server (Database is placed on server, its not downloaded to the client) You cannot use just JavaScript. For this you need Ajax! Here, let me help you through: 

    Link I am using is: http://w3schools.com/ajax/ajax_database.asp

    The tutorial page I am using is: http://w3schools.com/ajax/tryit.asp?filename=tryajax_database

    The code they have is: 

    function showCustomer(str)
    {
    var xmlhttp; // create a variable it can also be var xmlhttp = "";   
    if (str=="") // the str is created in variable, its value is given in the input or select field,
      {
      document.getElementById("txtHint").innerHTML=""; 
    // its a javascript property to get the element! txtHint is the id of the tag
      return;
      }
    if (window.XMLHttpRequest)
      {// code for IE7+, Firefox, Chrome, Opera, Safari
      xmlhttp=new XMLHttpRequest();
      }
    else
      {// code for IE6, IE5
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
    xmlhttp.onreadystatechange=function()
    // Ajax properties to check what is the state of page and request
      {
      if (xmlhttp.readyState==4 && xmlhttp.status==200)
    //readystate is 4= request finished and response ready! status 200 means request is OK, if page not found //than its 404, you know!
        {
        document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
    // now you will write the responce text in a field div with id txtHint! Pretty easy though
        }
      }
    xmlhttp.open("GET","getcustomer.asp?q="+str,true);
    // in .open() you set the request type, the page they are using is getcustomer, you use your own! 
    // and the remaining url! to fill the url at your need, this way you will get the response, as the users //types!
    xmlhttp.send();
    }

    I have shown you with examples and explaination. However I missed the input field, here goes: 

    <form action=""> 
    <select name="customers" onchange="showCustomer(this.value)">
    <option value="">Select a customer:</option>
    <option value="ALFKI">Alfreds Futterkiste</option>
    <option value="NORTS ">North/South</option>
    <option value="WOLZA">Wolski Zajazd</option>
    </select>
    </form>
    // The form is used to send the data, you know! But its nessecary as if user finds something to save, he can!
    <br>
    <div id="txtHint">Customer info will be listed here...</div>// here will be text written 'txtHint'

    Hope you get it!

    Saturday, July 13, 2013 1:22 AM
  • User1546138644 posted

    Thanks Afzaal, I will give that a try tonight... It looks like it might be axactly what I need!

    Also, now I know it's AJAX functionality I need I can research that as well.

    Thanks!

    Monday, July 15, 2013 9:09 AM
  • User895691971 posted

    Yes Ajax will not need that the form should be submitted! And it will continously send the data to server and check it just the way you want it to be checked. Like if there is already an email present in the Database, where as javascript or other code might need the form to be submitted, then sent to server, read and then sent back to tell whether its an error or not!

    Monday, July 15, 2013 10:00 AM
  • User-821857111 posted

    I would recommend using jQuery for your AJAX. Here's an old article I wrote that shows how to do this with a web forms web method (asmx).

    http://www.mikesdotnetting.com/Article/99/Preventing-duplicate-User-Names-with-ASP.NET-and-jQuery

    You can replace the WebMethod code for something that uses the database helper and put it into a .cshtml file instead. Here's a simple example that tests for "Pete". Call this CheckUser.cshtml:

     

    @{
        var reader = new StreamReader(Request.InputStream);
        var json = Json.Decode(reader.ReadToEnd());
        if(json.name == "Pete"){
            Json.Write(true, Response.Output);
        }
        else{
            Json.Write(false, Response.Output);
        }
    }

    And here's a form that makes use of it:

    @{
        
    }
    
    <!DOCTYPE html>
    
    <html lang="en">
        <head>
            <meta charset="utf-8" />
            <title></title>
            <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script> 
            <script type="text/javascript"> 
              $(function() {
                $("#Name").change(checkUser);
              });
     
              function checkUser() {
                $.ajax({
                  type: "POST",
                  url: "CheckUser/",
                  data: "{name: '" + $('#Name').val() + "'}",
                  contentType: "application/json; charset=utf-8",
                  dataType: "json",
                  success: function(data) {
                    $("#duplicate").empty();
                    if (data != "0") {
                      $("#duplicate").html(' That name has already been taken');
                    }
                  }
                });
              }
     
            </script> 
        </head>
        <body>
            <form method="post">
            <div>Name: </div>
            <div>@Html.TextBox("Name") <span id="duplicate"></span></div>
            </form>
        </body>
    </html>
    



    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, July 15, 2013 11:41 AM
  • User-821857111 posted

    That code is classic ASP. It won't work in ASP.NET.

    Monday, July 15, 2013 11:41 AM
  • User895691971 posted

    Afzaal.Ahmad.Zeeshan

    Link I am using is: http://w3schools.com/ajax/ajax_database.asp

    That code is classic ASP. It won't work in ASP.NET.

    You might be correct, but I still use that code! Its working perfectly.

    Monday, July 15, 2013 12:38 PM
  • User1546138644 posted

    No offence Afzaal, but I went with Mike's code as it is more aligned to ASP.NET.

    Worked a treat first time out of the box Cool

    One thing though- I move the script and function definitions into the <body> of a couple of pages that needed it, rather than in the <head> section, because I have a shared layout that reuses a shared <head> section for all pages. Is that ok? It works, but I am flying a bit blind on this stuff so maybe what I have done has implications I don't know about?

     

    Monday, July 15, 2013 2:24 PM
  • User-821857111 posted

    One thing though- I move the script and function definitions into the <body> of a couple of pages that needed it,

    That's fine. Actually, you can put it anywhere, but typically people either put these page-specific scripts towards the bottom of the page (just before the closing body tag) or in a separate .js file which is only included in the page that needs it.

    Monday, July 15, 2013 2:54 PM
  • User-821857111 posted

    I still use that code! Its working perfectly.

    In your case it probably will since you are only using the file as a kind of web service. You can add a .asp (classic ASP) file to a razor web site, but you should be aware that it is not part of the ASP.NET application. If you wanted to share session data with it for example, you have to jump through some extra hoops. Also, since it is not compiled, it will execute more slowly than a .NET page. 

    Monday, July 15, 2013 3:02 PM
  • User1546138644 posted

    Thanks Mike,

    Ah I like the idea of having them in a separate .js file I'll do that I think...

    One more question for you on this one- Is it possible to add further parameters to the data that gets passed to the function called on the field .OnChange? The implementation I now have means that if the user is updating an existing record and changes this key value, and on seeing the error message, retypes the old value into the field to try and put their mistake right, the function obviously gets called and informs them what they have entered duplicate data. So in fact I need to modify the code so that the check back to the database to search for dupes is only done OnChange when the current field name is not equal to what it was originally, if that makes sense?

     

    I think I can see where it would go, in the buildng up of the data string, but should there be a comma between values or what?

    Monday, July 15, 2013 3:02 PM
  • User-821857111 posted

    If you wanted to add further parameters to the post, you do it like this:

    data: "{name: '" + $('#Name').val() + "', param2 : 'some value'}",

    If you wanted to pass additional information back to the calling code, you can construct a dictionary and Json.Write that:

    @{
        var reader = new StreamReader(Request.InputStream);
        var json = Json.Decode(reader.ReadToEnd());
        var result = new Dictionary<string, object>();
        result.Add("submittedName", json.name);
        if(json.name == "Pete"){
            result.Add("response", true);
        }
        else{
            result.Add("response", false);
        }
        Json.Write(result, Response.Output);
    }

    Then your success handler would change a bit:

    success: function(data) {
        $("#duplicate").empty();
        if (data.response) {
            $("#duplicate").html(data.submittedName + ' is already been taken');
        }
    }

    Tuesday, July 16, 2013 12:32 AM
  • User1546138644 posted

    Hi, I only need to pass an additional value in, so I have modifed my code per your example above by adding the additional parameter.

    As long as my second variable is saved in a hidden form field I can retrieve it and pass it to the function. But I would prefer to pass it from a Razor variable- is that possible?

    For clarity the use case I am working on is this:

    1. On the "Amend" page, the user amends the value to a value in use elsewhere

    2. The current code detects this and posts the warning

    3. The user then goes back into the field and amends it again, back to what it was before. Now the current code would again check the value and find it clashes with a record in the database (which is the stored current record)

    To avoid this I want to pass the original value of the field to the checking function from before the user made any changes. I have that value stored in a Razor variable from when loaded the form default values, so all I want to do is pass that variable in. Then the function checks first to see if the current value of the field is the same as the original value in the field and skips the dupe check if it is.

    As I said, I can pass the old value in a hidden form field but I am wondering if I can pass the Razor variable instead?

    I have a JQuery and Javascript book on the way from Amazon now, following your revelations above, so hopefully I won't need to bug anyone on this again- I am finding this an amazingly powerful combination of technologies Cool

     

    Should I have made this a separate thread as the question and answer has now deviated from the original by some degrees?

     

     

     

     

    Wednesday, July 17, 2013 2:58 PM
  • User-821857111 posted

    If you want to add a Razor variable, you can do that:

    { param1: "@razorVariable" }
    



    Wednesday, July 17, 2013 3:42 PM
  • User1546138644 posted

    I had already tried that, and many similar variations on a theme, but in all cases the code remains shaded 'black' as if the syntax cannot be verified and fails to work. I assumed it is because it is not possible to pass razor variables across the languages in that way...

    data: "{name: '" + $('#bandName').val() + "', oldName: @oldBandName }",
    

     Note that oldBandName is a string

     

    Wednesday, July 17, 2013 4:19 PM
  • User-821857111 posted

    @oldname needs to go in quotes:

    data: "{name: '" + $('#bandName').val() + "', oldName: '@oldBandName' }",
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, July 18, 2013 12:31 AM
  • User1546138644 posted

    Well I could have sworn that was actually the first thing I tried... But anyhow, it is working now with the single quotes around the variable. Strangely though the script is still shaded black rather that the brown colour it was originally when the syntax was working on the single paramter in the data field... Is this a known issue with WM3? I have noticed before that the syntax validation sometimes gets confused...

    Thursday, July 18, 2013 1:45 AM