asp.net - Unable to get property 'value' of undefined or null reference -
i have registration form , button. onclick - call function on server side make validation of user's zip code @ database zipcodes. if validation passed - user's data stored in database (here continue use server function). if zipcode not match - call javascript function ask if user still wants save data db. , if yes - save using ajax request. problem when call javascript function - firstly should receive user's data on client side. when reading data happens - receive error "unable property 'value' of undefined or null reference". user's data still exist @ form's fields. seems data read server form once - reset somewhere - , can not read second time on client. here asp form
<body> <form id="frmzipvalidation" runat="server"> <div> <asp:label runat="server">registration form</asp:label> <asp:textbox runat="server" id="txtbxname"></asp:textbox> <asp:textbox runat="server" id="txtbxzipcode"></asp:textbox> <asp:dropdownlist runat="server" id="ddlcountry"> <asp:listitem text="select country" value="select" selected="true"></asp:listitem> <asp:listitem text="usa" value="usa"></asp:listitem> <asp:listitem text="canada" value="canada"></asp:listitem> </asp:dropdownlist> <asp:textbox runat="server" id="txtbxstate"></asp:textbox> <asp:textbox runat="server" id="txtbxcity"></asp:textbox> <asp:button runat="server" id="btnsubmit" text="submit" onclick="btnsubmit_click"/> </div> </form> </body> here server side
public partial class default : system.web.ui.page { string name; string zipcode; string country; string state; string city; bool ismatch; addresses dbaddresses = new addresses(); user newuser; protected void page_load(object sender, eventargs e) { if (request["action"] != null && request["action"].trim() != "") { if (request["action"] == "adduser") { adduser(request["name"], request["zipcode"], request["country"], request["state"], request["city"]); } } } private void adduser(string username, string userzip, string usercountry, string userstate, string usercity) { newuser = new user(username, userzip, usercountry, userstate, usercity); dbaddresses.users.add(newuser); dbaddresses.savechanges(); } protected void btnsubmit_click(object sender, eventargs e) { if (isvalid) { zipcode = txtbxzipcode.text; country = ddlcountry.text; state = txtbxstate.text; city = txtbxcity.text; name = txtbxname.text; ismatch = false; list<zipcode> zipc = (from z in dbaddresses.zips z.zip == zipcode select z).tolist(); //if zipcode entered client not exists @ database return false if (!zipc.any()) { ismatch = false; } else { (int = 0; < zipc.count; i++) { if (zipc[i].country.tostring() == country) { if (zipc[i].state.tostring() == state) { if (zipc[i].city.tostring() == city) { adduser(name, zipcode, country, state, city); //message user saved page.clientscript.registerclientscriptblock(typeof(page), "1", "<script>alert('your data saved successfully!');</script>"); ismatch = true; break; } else { ismatch = false; break; } } else { ismatch = false; break; } } else { ismatch = false; break; } } } //if user's data not match, go js client code - if user wants in case save data - make using ajax request if (!ismatch) { string clientscript = "ajaxrequestsavetodb();"; this.page.clientscript.registerstartupscript(this.gettype(), "myclientscript", clientscript); } } } } and here javascript:
function ajaxrequestsavetodb() { var savedata = confirm('zip/postal code doesn’t match region. sure want save data?'); if (savedata) { var username = document.getelementbyid('txtbxname').value; var userzipcode = document.getelementbyid('txtbxzipcode').value; var usercountry = document.getelementbyid('ddlcountry').value; var userstate = document.getelementbyid('txtbxstate').value; var usercity = document.getelementbyid('txtbxcity').value; senddatatoserver('adduser', username, userzipcode, usercountry, userstate, usercity); alert("you data saved successfully!"); } else { alert('not saved'); } } } function senddatatoserver(requesttype, name, zipcode, country, state, city) { var xmlhttp = getxmlhttp(); var url = "default.aspx?action=" + escape(requesttype) + "&name=" + escape(name) + "&zipcode=" + escape(zipcode) + "&country=" + escape(country) + "&state=" + escape(state) + "&city=" + escape(city); xmlhttp.open("get", url, true); xmlhttp.send(); }
a short book client-server communications using "custom" ajax requests.
in asp.net programming (almost) every time client interacts server, client sends of information server , throws out old content , replaces response client received server. problem running asp:button on client machine sending information .aspx page on server , server interpreting information, realizing wrong , telling client should ask user more information throw out information had been entered.
the best way have found around problem use call "custom ajax requests." means write string of xml , send asp handler page set accept xml string , it. in travels have slimmed down 3 parts. first user interface contains of markup , css(and validation), second javascript file contains of data gathering , actual ajax request , lastly there ashx file handles request client.
so start need set user interface. along lines of:
<body> <form id="frmzipvalidation" runat="server"> <div> <div class="label">registration form<div> <asp:textbox id="txtbxname" class="txtbxname" clientidmode="static" runat="server"></asp:textbox> <asp:textbox id="txtbxzipcode" class="txtbxzipcode" clientidmode="static" runat="server" ></asp:textbox> <asp:dropdownlist id="ddlcountry" class="ddlcountry" clientidmode="static" runat="server" > <asp:listitem text="select country" value="select" selected="true"></asp:listitem> <asp:listitem text="usa" value="usa"></asp:listitem> <asp:listitem text="canada" value="canada"></asp:listitem> </asp:dropdownlist> <asp:textbox id="txtbxstate" class="txtbxstate" clientidmode="static" runat="server" ></asp:textbox> <asp:textbox id="txtbxcity" class="txtbxcity" clientidmode="static" runat="server" ></asp:textbox> <input id="btnsubmit" class="btnsubmit" type="button" value="save" onclick="submitform()" /> </div> </form> </body> couple things note this:
- the button submit form not asp button html button.
- all of input controls asp controls have
clientidmodesetstatic, work in .net 4.0 or higher. - we set
classsame thingidin case aren't using .net 4.0 or higher. css classes want add control can added after dummy id class.(for examples i'm assuming in .net 4.0 can switch them work withoutclientidmodeattribute if need)
the second piece puzzle javascript. there couple ways can accomplish need. first using vanilla js without of plugins or external libraries. saves small amount of processing time, marginal amount of loading time , can accomplish ask of it. but, if include external library, jquery, , plugin, jquery validation, can make our lives whole heck of lot easier during programming phase reducing amount of code have write factor of 10. , if concerned load times can use client cache store external libraries have download them once. whether or not decide use external javascript libraries project needs since concerned validating zip code not empty not use jquery thought worth mentioning because of how streamlined makes process.
once ready submit form first step validate zipcode valid. can couple ways depending on how in depth want get. quickest check verify zip code text box not empty when button clicked. need do:
function submitform() { //this assigned click handler on button in html if (document.getelementbyid('txtbxzipcode').value != null && document.getelementbyid('txtbxzipcode').value != '') { save('yourhandler', getquerystring, getxmlstring, successhandler, failurehandler); } else { //your user needs know went wrong... } } so, down meat , potatoes of whole situation. ajax request. i've come reusable function handles entire ajax request looks like:
function save(handlername, getquerystring, getxmlstring, successhandler, failurehandler) { // date.gettime gets number of milliseconds since 1 january 1970, divide 1000 seconds. end = (new date().gettime() / 1000) + 30; //this variable actual ajax request. object works ie8+ if want backwards compatability earlier versions need different object can dig if need. var xmlhttp = new xmlhttprequest(); //this function fires everytime status of request changes. xmlhttp.onreadystatechange = function () { if (xmlhttp.readystate == 4 && xmlhttp.status == 200) { //get headers determine whether or not request successful. header need add response manually. var xx = xmlhttp.getresponseheader("success"); //the object xx string designate. chose use true indicator successful because intuitive. var x1 = xx.trim(); if (x1 != undefined && x1 == 'true' && (new date().gettime() / 1000) < end) { //if response successful , timeout hasn't elapsed xml response , call success handler var xmlresponse = xmlhttp.responsexml; successhandler(sender, xmlresponse); } else if ((new date().gettime() / 1000) < end) { //if response not successful , timeout hasn't elapsed xml response , call failure handler var xmlresponse = xmlhttp.responsexml; failurehandler(sender, xmlresponse); } //if request successful } //if readystate 4 , status 200 } //onreadystatechanged function //this gets query string added url var varstring = getquerystring(); //build xml string send server var xmlstring = getxmlstring(); //open request using handler name passed in , querystring got function passed in xmlhttp.open("post", "../requesthandlers/" + handlername + ".ashx" + varstring, true); //this tells handler content of request xml xmlhttp.setrequestheader("content-type", "text/xml"); //send request using xml got other function passed in. xmlhttp.send(xmlstring); } this function has built in timeout makes if server takes more 30 seconds respond request response client receives ignored. implementations combined function displays user tell them website working on request , if time out elapses tells them time out occurred.
the second thing function assumes handlers in folder next root of website named requesthandlers. use set consolidate of handler files can change looking wherever want.
the function takes in string , 4 function pointers. string represents name of handler waiting interpret request, 4 function pointers have specific jobs.
the first function pointer getquerystring represents function have write append variables deem necessary end of url being posted to. this site gives pretty accurate explanation of query string should used for. me common getquerystring function looks like:
function getpaymentquerystring() { var varstring = ''; varstring = "?ccpayment=true"; return varstring; } the second function pointer, getxmlstring, used create xml string(go figure...) sent handler page posting to. string represent bulk of request. should not shown snooping requests should sent xml string, if paranoid can send encrypted xml string that's not, strictly speaking, necessary. depends on sending, if complete credit card information then, yeah, maybe want consider it, if first , last names encrypting overkill.
a common getxmlstring function might like:
function getpaymentxmlstring() { var xmlstring = ''; xmlstring = '<?xml version="1.0" encoding="utf-8"?><address><zipcode>' + document.getelementbyid('txtbxzipcode').value + '</zipcode></address>'; return xmlstring; } the important part of function xml right. first tag pretty universal , should fine use in situations , after matching tags up. left out lot of fields save space.
the last 2 function pointers want call if goes planned , if fails respectively. way handle successful requests hide inputs whole(usually putting them inside of own div section) , displaying confirmation message of sort. failed requests can bit trickier because have tell user why failed. way having dummy div section above else on page sort of special css attached makes div stand out in way , if request fails send string of text server best guess of why failed , assign displayed in div section. how decide display results user dictated project itself. since when succeeds or fails on project project basis can't give generic example of should part on own.
now have pieces in place, last piece make handler.
basically intents , purposes handler aspx webpage nothing on it. html makes handler pages, have extension .ashx, like:
<%@ webhandler language="vb" codebehind="yourhandler.ashx.cs" class="yourhandler" %> and that's it. there should no other markup in actual .ashx file. name of handler change depending on doing.
the code behind when creating ashx file default class contains single function named processrequest. can treat function sort of "request received" event. in case move content of btnsubmit_click function processrequest function in ashx file. can add properties or other functions want processrequest function must present handler work far know.
one step need information xml sent handler , tell response sending xml client.
so xml request need do:
io.streamreader textreader = new io.streamreader(context.request.inputstream); context.request.inputstream.seek(0, io.seekorigin.begin); textreader.discardbuffereddata(); xdocument xml = xdocument.load(textreader); string zip = xml.elements("address").elements("zipcode").firstordefault().value; in order send xml client need add couple headers response , accomplish adding(i think correct way implement interface in c# not positive on point though):
class yourhandler : system.web.ihttphandler, system.web.sessionstate.ireadonlysessionstate under class definition and:
context.response.contenttype = "text/xml"; context.response.contentencoding = system.text.encoding.utf8; context.response.cache.setcacheability(httpcacheability.nocache); context.response.cache.setallowresponseinbrowserhistory(true); to beginning of processrequest function. 6 lines tell client receiving xml , not cache of response ensure clients see up-to-date content.
so. there is. should have framework validate user input, create ajax request, send request custom handler, accept xml client, write xml client , display res-...i knew forgot something...
what client supposed xml gets server? throw @ wall , see sticks? no won't work. you'll need way interpret xml on client side. luckily xmlhttprequest object has been written make task lot easier sounds.
you may have noticed set success , failure handlers take sender object , xml object. sender overkill , can ignored(or removed) example work fine. xml object concerned now. before client side must mention have go through same process on server side did on client side , manually write xml string including values want client know about. example i'm going assume want display friendlymessage user. write response client like:
using (system.xml.xmltextwriter writer = new system.xml.xmltextwriter(context.response.output)) { context.response.addheader("success", true); system.xml.xmldocument doc = new system.xml.xmldocument(); doc.loadxml("<?xml version='1.0' encoding='utf-8'?><response><friendlymessage>" + message + "</friendlymessage></response>"); doc.writeto(writer); writer.flush(); writer.close(); } on client side friendlymessage xml need do:
xml.getelementsbytagname("friendlymessage")[0].childnodes[0].nodevalue now line makes few assumptions. like, may want add checks in make sure xml.getelementsbytagname("friendlymessage") has children before trying evaluate them. sorts of checks discretion.
this time think i've covered steps. hope "little" guide helps , didn't bore much. apologize length sort of process getting right takes few steps. once base line in place , working lends situation. layout makes user experience better having them wait full trips server each time.
i sincerely hope helps project done , haven't skipped step or equally embarrassing...
Comments
Post a Comment