Validation with ajax AutoCompleteExtender - asp.net

I have a TextBox with AutoCompleteExtenderwhen the person starts typing in the TextBox List with City name Appear .This works fine but now I want to validate that if they just type in a textbox and don't select one from the list that it validates that City Is Not Exist In database.
I want to validate it Using Ajax And Without PostBack Before Final Submit of form.

Add new js file with content below and add add reference on it to ToolkitScriptManager's Scrips collection:
Type.registerNamespace('Sjax');
Sjax.XMLHttpSyncExecutor = function () {
Sjax.XMLHttpSyncExecutor.initializeBase(this);
this._started = false;
this._responseAvailable = false;
this._onReceiveHandler = null;
this._xmlHttpRequest = null;
this.get_aborted = function () {
//Parameter validation code removed here...
return false;
}
this.get_responseAvailable = function () {
//Parameter validation code removed here...
return this._responseAvailable;
}
this.get_responseData = function () {
//Parameter validation code removed here...
return this._xmlHttpRequest.responseText;
}
this.get_started = function () {
//Parameter validation code removed here...
return this._started;
}
this.get_statusCode = function () {
//Parameter validation code removed here...
return this._xmlHttpRequest.status;
}
this.get_statusText = function () {
//Parameter validation code removed here...
return this._xmlHttpRequest.statusText;
}
this.get_xml = function () {
//Code removed
}
this.executeRequest = function () {
//Parameter validation code removed here...
var webRequest = this.get_webRequest();
if (webRequest === null) {
throw Error.invalidOperation(Sys.Res.nullWebRequest);
}
var body = webRequest.get_body();
var headers = webRequest.get_headers();
var verb = webRequest.get_httpVerb();
var xmlHttpRequest = new XMLHttpRequest();
this._onReceiveHandler = Function.createCallback(this._onReadyStateChange, { sender: this });
this._started = true;
xmlHttpRequest.onreadystatechange = this._onReceiveHandler;
xmlHttpRequest.open(verb, webRequest.getResolvedUrl(), false); // False to call Synchronously
if (headers) {
for (var header in headers) {
var val = headers[header];
if (typeof (val) !== "function") {
xmlHttpRequest.setRequestHeader(header, val);
}
}
}
if (verb.toLowerCase() === "post") {
if ((headers === null) || !headers['Content-Type']) {
xmlHttpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
if (!body) {
body = '';
}
}
this._started = true;
this._xmlHttpRequest = xmlHttpRequest;
xmlHttpRequest.send(body);
}
this.getAllResponseHeaders = function () {
//Parameter validation code removed here...
return this._xmlHttpRequest.getAllResponseHeaders();
}
this.getResponseHeader = function (header) {
//Parameter validation code removed here...
return this._xmlHttpRequest.getResponseHeader(header);
}
this._onReadyStateChange = function (e, args) {
var executor = args.sender;
if (executor._xmlHttpRequest && executor._xmlHttpRequest.readyState === 4) {
//Validation code removed here...
executor._responseAvailable = true;
executor._xmlHttpRequest.onreadystatechange = Function.emptyMethod;
executor._onReceiveHandler = null;
executor._started = false;
var webRequest = executor.get_webRequest();
webRequest.completed(Sys.EventArgs.Empty);
//Once the completed callback handler has processed the data it needs from the XML HTTP request we can clean up
executor._xmlHttpRequest = null;
}
}
}
Sjax.XMLHttpSyncExecutor.registerClass('Sjax.XMLHttpSyncExecutor', Sys.Net.WebRequestExecutor);
On a page:
<ajaxToolkit:ToolkitScriptManager runat="server" ID="ScriptManager1">
<Scripts>
<asp:ScriptReference Path="~/XMLHttpSyncExecutor.js" />
</Scripts>
</ajaxToolkit:ToolkitScriptManager>
Then, add CustomValidator for target TextBox and use function below for client validation:
<asp:TextBox runat="server" ID="myTextBox" Width="300" autocomplete="off" />
<asp:CustomValidator runat="server" ID="myTbCustomValidator" ControlToValidate="myTextBox"
Text="*" Display="Dynamic" ValidateEmptyText="false" ClientValidationFunction="validateTextBox"
OnServerValidate="ValidateTextBox" />
function validateTextBox(sender, args) {
if (args.Value.length > 0) {
var extender = $find("AutoCompleteEx"); // AutoComplete extender's BehaviorID
if (extender._completionListElement) {
var children = extender._completionListElement.childNodes;
var length = extender._completionListElement.childNodes.length;
for (var i = 0; i < length; i++) {
if (children[i].innerHTML == args.Value) {
args.IsValid = true;
return;
}
}
}
var request = new Sys.Net.WebRequest();
request.set_url('<%= ResolveClientUrl("~/AutoComplete/AutoComplete.asmx/Validate") %>');
var body = Sys.Serialization.JavaScriptSerializer.serialize({ value: args.Value });
request.set_body(body);
request.set_httpVerb("POST");
request.get_headers()["Content-Type"] = "application/json; encoding=utf-8";
request.add_completed(function (eventArgs) {
var result = Sys.Serialization.JavaScriptSerializer.deserialize(eventArgs.get_responseData());
args.IsValid = result.d;
});
var executor = new Sjax.XMLHttpSyncExecutor();
request.set_executor(executor);
request.invoke();
}
}
The main idea of code above is to check suggested items at first for entered text and if there aren't any concidence then to do synchronous AJAX call to Validate method of web service or page method. That method should have such signature: public bool Validate(string value)
P.S. Code for XMLHttpSyncExecutor taken here: Using Synchronous ASP.Net AJAX Web Service Calls and Scriptaculous to Test your JavaScript

Related

my action method returning {"success=true,message="work done"} ASP.net MVC 5

Here is my create action method. I want get alert form it when success is true.
public JsonResult Create(Student student ,HttpPostedFileBase img)
{
if (ModelState.IsValid)
{
if (img !=null)
{
var name = Path.GetFileNameWithoutExtension(img.FileName);
var ext = Path.GetExtension(img.FileName);
var filename = name + DateTime.Now.ToString("ddmmyyyff") + ext;
img.SaveAs(Server.MapPath("~/img/"+filename));
student.ImageName = filename;
student.Path = "~/img/" + filename;
}
db.Students.Add(student);
db.SaveChanges();
return Json(new { success = true, responseText = "The attached file is not supported." }, JsonRequestBehavior.AllowGet);
}
ViewBag.ClassID = new SelectList(db.Classes, "Id", "Name", student.ClassID);
return new JsonResult { Data = new { success = false, message = "data not saved" } };
}
Here is my ajax function :
function onsub(form) {
$.validations.unobtrusive.parse(form);
if (form.valid()) {
var ajaxConfig = {
type: "POST",
url: form.action,
data: new FormData(form),
success: function (response) {
if (response.success ) {
alert(response.responseText);
} else {
// DoSomethingElse()
alert(response.responseText);
}
}
}
if ($(form).attr("enctype") == "multipart/form-data") {
ajaxConfig["contentType"] = false;
ajaxConfig["processData"] = false;
}
$.ajax(ajaxConfig);
}
return false;
}
How can I get an alert form it
without reloading the form. I also want to submit images and other files to create an action method.
This is the result that I get after submitting the form:
In your case you are calling Create action which returning the JSON Result and the same Json response is displayed in browser.
Their should be a View page from where you will call this method by using the Ajax call, then you will be able to see your alert message.

ASP.NET display progress bar during post back

I have a fileupload control on a form and a button. Once a button is clicked the server converts the file into a datatable and loops through datatable records for validation purposes.
My problem: the validation process takes a long time, so i wanted to display current item being processed to user.
My attempts: i found Ajax and SignalR being implemented in such scenarios. However, Ajax requires an update panel to work which cannot work with the updatefile control. I tried SignalR and it works however, it cannot work during a postback --> apparently.
Can anyone assist me in finding a solution.
Thank you!
Hey you can use ModalPopupExtender of ajaxToolkit something like this
<ajaxToolkit:ModalPopupExtender ID="ProgressBarModalPopupExtender" runat="server"
BackgroundCssClass="ModalBackground" BehaviorID="ProgressBarModalPopupExtender"
TargetControlID="hiddenField" PopupControlID="Panel1" DynamicServicePath="" Enabled="True" />
<asp:Panel ID="Panel1" runat="server" Style="display: none; background-color: #C0C0C0;">
<p class="wait">Please wait!</p>
</asp:Panel>
<asp:HiddenField ID="hiddenField" runat="server" />
add the above code any where on your page then on your button of file upload try this
<input type="submit" value="Upload" id="upload"
causesvalidation="False" onclick="javascript:return validateAdd();"
onserverclick="btnupload_ServerClick" runat="server" />
in javascript
function validateAdd() {
var myExtender = $find('ProgressBarModalPopupExtender');
myExtender.show();
return true;
}
and in code behind
protected void btnupload_ServerClick(object sender, EventArgs e)
{
// your code of upload
//
// your code of upload
ProgressBarModalPopupExtender.Hide();
}
this shall do
If you only target HTML5 users you can use the FileReader class and stream the file with ajax. This will work with SignalR
I did it like this in my project, maybe it can give you some pointers
(function(app) {
app.FileUploadViewModel = app.define({
init: function (parent, file, callback) {
this.kb = 1024;
this.bufferSize = this.kb * 512;
this.speedSampleAt = this.bufferSize;
this.file = file;
this.parent = parent;
this.reader = new FileReader();
this.total = this.file.size / this.bufferSize;
this.current = ko.observable(0);
this.progress = ko.computed(this.getProgress, this);
this.speed = ko.observable(0);
this.speedText = ko.computed(this.getSpeedText, this);
this.name = this.file.name;
this.reader.onload = this.onLoadPart.bind(this);
this.callback = callback;
this.createStream();
},
prototype: {
createStream: function() {
app.utils.post("api/upload/createstream", {
parentId: this.parent.id,
filename: this.file.name
}, function (id) {
this.id = id;
this.loadPart();
}.bind(this));
},
getSpeedText: function() {
return Math.round(this.speed()) + " Mbit / s";
},
getProgress: function () {
return (this.current() / this.total * 100) + "%";
},
loadPart: function () {
var start = this.current() * this.bufferSize;
this.calculateSpeed(start);
var blob = this.file.slice(start, start + this.bufferSize);
this.done = blob.size != this.bufferSize || blob.size === 0;
this.reader.readAsDataURL(blob);
},
onLoadPart: function (part) {
if (part.loaded === 0) {
this.onPartTransfered();
} else {
var base64 = part.target.result.substr(part.target.result.indexOf(",") + 1);
app.utils.post("api/upload/Part", { id: this.id, data: base64 }, this.onPartTransfered.bind(this));
}
},
onPartTransfered: function () {
this.current(this.current() + 1);
if (this.done) {
this.callback(this);
app.utils.post("api/upload/closestream", this.id, function (file) {
this.parent.addChild(file);
}.bind(this));
} else {
this.loadPart();
}
},
calculateSpeed: function (position) {
if (this.lastSpeedSample === undefined) {
this.lastSpeedSample = new Date();
}
if (position % this.speedSampleAt === 0) {
var delta = new Date() - this.lastSpeedSample;
var seconds = delta / 1000;
var mbit = this.speedSampleAt / this.kb / this.kb * 8;
var speed = mbit / seconds;
this.lastSpeedSample = new Date();
this.speed(speed);
}
}
}
});
})(window.Filebrowser = window.Filebrowser || {});

Page Got Postback in OnClientClick Return False

I am working in C#.Net. i am having an asp button..
<asp:Button ID="btnSubmitData" ToolTip="Show" runat="server" Text="SHOW" CausesValidation="false"
OnClientClick="return FindSelectedItems();" OnClick="btnShow_Click" />
The function called in OnClientClick is,
function FindSelectedItems() {
var sender = document.getElementById('lstMultipleValues');
var cblstTable = document.getElementById(sender.id);
var checkBoxPrefix = sender.id + "_";
var noOfOptions = cblstTable.rows.length;
var selectedText = "";
var total = 0;
for (i = 0; i < noOfOptions; ++i) {
if (document.getElementById(checkBoxPrefix + i).checked) {
total += 1;
if (selectedText == "")
selectedText = document.getElementById
(checkBoxPrefix + i).parentNode.innerText;
else
selectedText = selectedText + "," +
document.getElementById(checkBoxPrefix + i).parentNode.innerText;
}
}
var hifMet1 = document.getElementById('<%=hifMet1.ClientID%>');
hifMet1.value = selectedText;
if (total == 0) {
var panel = document.getElementById('<%=pnlOk.ClientID%>');
document.getElementById('<%=pnlOk.ClientID%>').style.display = 'block';
var Label1 = document.getElementById('<%=Label3.ClientID%>');
Label1.innerHTML = "Atleast one metric should be selected.";
var btnLoc = document.getElementById('<%=btnLoc.ClientID%>');
btnLoc.disabled = true;
var btnProd = document.getElementById('<%=btnProd.ClientID%>');
btnProd.disabled = true;
var btnLastYear = document.getElementById('<%=btnLastYear.ClientID%>');
btnLastYear.disabled = true;
return false;
}
else if (total > 2) {
var panel = document.getElementById('<%=pnlOk.ClientID%>');
document.getElementById('<%=pnlOk.ClientID%>').style.display = 'block';
var Label1 = document.getElementById('<%=Label3.ClientID%>');
Label1.innerHTML = "Only two metrics can be compared.";
var btnLoc = document.getElementById('<%=btnLoc.ClientID%>');
btnLoc.disabled = true;
var btnProd = document.getElementById('<%=btnProd.ClientID%>');
btnProd.disabled = true;
var btnLastYear = document.getElementById('<%=btnLastYear.ClientID%>');
btnLastYear.disabled = true;
return false;
}
else {
return true;
}
}
Once i click the SHOW Button, i need to do a validation to check at least one checkbox should get checked in checkbox list. That alert message i am getting (i.e) "Atleast one metric should be selected". But after this part, the page gets reloaded.
I want to avoid the page refresh at this point. What should i do here.?
One way is to hook your validation function into the proper ASP .Net validation lifecycle by using a CustomValidator control and a client validation function.
With a few minor changes you can turn your JavaScript code into a client validation function.
Full example here.
Relevant Snippets
<script language="javascript">
function ClientValidate(source, arguments)
{
// Your code would go here, and set the IsValid property of arguments instead
// of returning true/false
if (arguments.Value % 2 == 0 ){
arguments.IsValid = true;
} else {
arguments.IsValid = false;
}
}
</script>
<asp:CustomValidator id="CustomValidator1"
ControlToValidate="Text1"
ClientValidationFunction="ClientValidate"
OnServerValidate="ServerValidation"
Display="Static"
ErrorMessage="Not an even number!"
ForeColor="green"
Font-Name="verdana"
Font-Size="10pt"
runat="server"/>
<asp:Button id="Button1"
Text="Validate"
OnClick="ValidateBtn_OnClick"
runat="server"/>
Client validation should always be double-checked with server validation; using a CustomValidator with both client/server validation functions is a good way to accomplish this.
Remove script
else {
return true;
}
part from script and call function like this
OnClientClick="javascript:return FindSelectedItems();"
This work for me.

How can I use the ContextKeys property for the AjaxFileUpload control?

I started looking at the AjaxFileUpload control, specifically the ContextKeys property. However, I do not understand how to use it.
The documentation says of AjaxFileUpload that the ContextKeys is used to pass information to the server when a file is uploaded. But no examples are provided. Are there any examples online that I could look at?
Though such functionality not implemented (I believe it was planned but by some reasons was postponed), nothing protect you from implement it yourself. To do this you need to download AjaxControlToolkit source code and tweak it for your needs.
There will be a lot of points so you may to prepare a cup of coffee before :)
I'll show changes with name of file that must being changed.
Server/AjaxControlToolkit/AjaxFileUpload/AjaxFileUpload.cs file
First of all, add ContextKeys property to the AjaxFileUploadEventArgs.cs file (it located in same folder):
/// <summary>
/// Gets or sets the context keys.
/// </summary>
public string ContextKeys
{
get;
set;
}
After that open the AjaxFileUpload class code and change the OnPreRender method. Here is a part of this method with custom modifications:
var eventArgs = new AjaxFileUploadEventArgs(guid, AjaxFileUploadState.Success,
"Success", uploadedFile.FileName,
uploadedFile.ContentLength, uploadedFile.ContentType,
stream.ToArray());
// NEW CODE HERE
eventArgs.ContextKeys = this.Page.Request.Form["contextKeys"];
That's all changes in server code we need. Now we need to modify the Sys.Extended.UI.AjaxFileUpload client class (file AjaxFileUpload.pre.js )
Firstly let's modify _html5UploadFile method as below:
_html5UploadFile: function (fileItem) {
this._guid = Sys.Extended.UI.AjaxFileUpload.utils.generateGuid();
var uploadableFile = fileItem.get_fileInputElement();
var fd = new FormData();
fd.append("fileId", uploadableFile.id);
fd.append("Filedata", uploadableFile.file);
if (this.contextKeys) {
if (typeof this.contextKeys !== "string") {
this.contextKeys = Sys.Serialization.JavaScriptSerializer.serialize(this.contextKeys);
}
fd.append("contextKeys", this.contextKeys);
}
$common.setVisible(this._progressBar, true);
this._setDisableControls(true);
this._html5SetPercent(0);
this._setStatusMessage(String.format(Sys.Extended.UI.Resources.AjaxFileUpload_UploadingHtml5File, uploadableFile.file.name, Sys.Extended.UI.AjaxFileUpload.utils.sizeToString(uploadableFile.file.size)));
var url = this._postBackUrl;
if (url.indexOf("?") != -1)
url += "&";
else
url += "?";
this._webRequest = new Sys.Net.WebRequest();
this._executor = new Sys.Net.XMLHttpExecutor();
this._webRequest.set_url(url + 'contextkey=' + this._contextKey + '&guid=' + this._guid);
this._webRequest.set_httpVerb("POST");
this._webRequest.add_completed(this.bind(this._html5OnRequestCompleted, this));
//this._executor.add_load(this.bind(this._html5OnComplete, this));
this._executor.add_progress(this.bind(this._html5OnProgress, this));
this._executor.add_uploadAbort(this.bind(this._html5OnAbort, this));
this._executor.add_error(this.bind(this._html5OnError, this));
this._webRequest.set_executor(this._executor);
this._executor.executeRequest(fd);
}
As you can see above, we adding contextKeys to form data, posted with Ajax request.
The we need to modify the _uploadInputElement method:
_uploadInputElement: function (fileItem) {
var inputElement = fileItem.get_fileInputElement();
var uploader = this;
uploader._guid = Sys.Extended.UI.AjaxFileUpload.utils.generateGuid();
setTimeout(function () {
uploader._setStatusMessage(String.format(Sys.Extended.UI.Resources.AjaxFileUpload_UploadingInputFile, Sys.Extended.UI.AjaxFileUpload.utils.getFileName(inputElement.value)));
uploader._setDisableControls(true);
uploader.setThrobber(true);
}, 0);
var url = uploader._postBackUrl;
if (url.indexOf("?") != -1)
url += "&";
else
url += "?";
uploader._createVForm();
uploader._vForm.appendChild(inputElement);
if (this.contextKeys) {
if (typeof this.contextKeys !== "string") {
this.contextKeys = Sys.Serialization.JavaScriptSerializer.serialize(this.contextKeys);
}
var contextKeysInput = document.createElement("input");
contextKeysInput.setAttribute("type", "hidden");
contextKeysInput.setAttribute("name", "contextKeys");
contextKeysInput.setAttribute("value", this.contextKeys);
uploader._vForm.appendChild(contextKeysInput);
}
uploader._vForm.action = url + 'contextkey=' + this._contextKey + '&guid=' + this._guid;
uploader._vForm.target = uploader._iframeName;
setTimeout(function () {
uploader._vForm.submit();
uploader._waitTimer = setTimeout(function () { uploader._wait() }, 100);
}, 0);
}
After all these changes you can set ContextKeys property in code-behind and get it value from AjaxFileUploadEventArgs argument of the UploadComplete event as below:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack && !AjaxFileUpload1.IsInFileUploadPostBack)
{
AjaxFileUpload1.ContextKeys = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(new Dictionary<string, string> { { "1", "First" }, { "2", "Second" } });
}
protected void AjaxFileUpload1_OnUploadComplete(object sender, AjaxFileUploadEventArgs file)
{
if (!string.IsNullOrEmpty(file.ContextKeys))
{
var contextKeys = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Dictionary<string, string>>(file.ContextKeys);
}
Also, if you'll implement OnClientUploadStarted client-side event as proposed here link, you may pass to server your contextKeys from client:
function uploadStarted(sender, args) {
sender.contextKeys = { "first": "1", "second": "2" };
}

runtime generated Checkbox validation

I have panel in the asp.net webpage, and i m generating the checkbox at runtime..
i want to validate checkbox, required field validator when form submit.
here is my code:
cv = new CustomValidator();
cv.ID = "cv" + "_" + dt.Rows[0]["RefQueID"].ToString();
cv.ValidationGroup = "grp";
cv.Display = ValidatorDisplay.None;
cv.ErrorMessage = "- Question " + intQuestionNo.ToString();
cv.ClientValidationFunction = "chkCount";
cv.Attributes.Add("rfvid", cv.ID.ToString());
//this portion of code is for custom validation javascript function
StringBuilder sb = new StringBuilder();
sb.Append("<script type='text/javascript'> function chkCount(sender,args) { ");
sb.Append(" args.IsValid = GetChk(document.getElementById('ctl00_ContentPlaceHolder1_" + cbl.ID.ToString() + "'))");
sb.Append(" } </script>");
Page page = HttpContext.Current.Handler as Page;
page.RegisterStartupScript("_Check", sb.ToString());
and in my javascript function i return this:
function GetChk(chkbox, args) {
if (!isConfirmed) {
alert('hi');
var chkBoxList = document.getElementById(chkbox.ClientID);
var chkBoxCount = chkBoxList.getElementsByTagName("input");
for (var i = 0; i < chkBoxCount.length; i++) {
if (chkBoxCount[i].checked == true) {
return true;
}
}
return false;
}
return true;
}
but i m not getting the value of the checkbox...
required value:=
ctl00_ContentPlaceHolder1_tc_hospital_improvement_features_tp_Reflection_cbl_116_0
Actual Value:=
ctl00_ContentPlaceHolder1_tc_hospital_improvement_features_tp_complete_stage_chk_confirm
pls help...
first get the runtime generated control into the codebehind file from class file.
and then secondly after getting the control property, we can validate the checbox list.
Get the control into codebehind file from class file.
CheckBoxList cbl = (CheckBoxList)pnlref.FindControl("cbl_116");
provide the javascript validation to the runtime generated checkbox list.
function GetChk(chkbox, args) {
if (!isConfirmed) {
var chkBoxList = document.getElementById('ctl00_ContentPlaceHolder1_tc_hospital_improvement_features_tp_Reflection_cbl_116');
var chkBoxCount = chkBoxList.getElementsByTagName("input");
for (var i = 0; i < chkBoxCount.length; i++) {
if (chkBoxCount[i].checked == true) {
return true;
}
}
return false;
}
return true;
}

Resources