I have an ASP.NET form that calls a web service using ASP.NET AJAX. How do I make the call synchronous?
// test.aspx
<script type="text/javascript">
function GetDescription(){
var code = document.getElementById("<%=txtCode.ClientID%>").value;
var description =
MyNamespace.MyService.GetDescription(
code, onSuccessGetDescription, null, null);
return false;
}
function OnSuccessGetDescription(result){
var txtDescription =
document.getElementById("<%=txtDescription.ClientID%>");
}
</script>
<script type="text/javascript">
$(document).ready(//function () {
$('#<%=cmdSave.ClientID%>').click(function (e) {
e.preventDefault();
if (Page_ClientValidate()){
// Populate jQuery.UI dialog box with code and description
// and then
$("#confirm-dialog").dialog("open");
}
});
}
</script>
<asp:TextBox ID="txtCode" />
<asp:TextBox ID="txtDescription" />
<asp:Button ID="cmdSave" />
// test.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
txtCode.Attributes["onblur"] = "GetDescription();";
}
The answers to this question that I have seen say that I should set the async attribute to false, but I don't see how to do that here.
ASP.Net Ajax - PageMethods Synchronous call and retrieval of results says that it can't be done. I am trying to get a second opinion.
If I can't make the call synchronous, would it be legal to make GetTransaction poll until the OnSuccess function returns? What would be an efficient (i.e. not CPU-intensive) way to do that?
JQuery Asynchronous
jQuery.ajax({
url: 'http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
success: function (result) {
if (result.isOk == false) alert(result.message);
},
async: false
});
Related
I have many buttons and when the user clicks on one, I want it to update a label with ajax.
I implemented ajax in my template like so:
<form runat="server">
<asp:ScriptManager ID="ScriptManagerPull" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div runat="server" id="SiteContent">
</div>
</ContentTemplate>
</asp:UpdatePanel>
</form>
The buttons are generated dynamically;
foreach (MyDTO myDTO in List) {
Button ButtonPull = new Button();
ButtonPull.Text = "Pull";
ButtonPull.ID = articleDTO.ArticleID.ToString();
ButtonPull.ControlStyle.CssClass = "btn btn-default";
ButtonPull.Click += new EventHandler(Pull_Click);
SiteContent.Controls.Add(ButtonPull);
}
Now the problem is that the event doesn't get called when a user clicks on button. This doesn't work:
protected void Pull_Click(object sender, EventArgs e) {
// Button button = sender as Button;
LabelTest.Text = "Cool";
}
How can I do that?
Thanks.
I am assuming you do not simply want to call the click event but perhaps pass some data from the client to the server via AJAX. The most straightforward way to do this, without ScriptManager, UpdatePantel and all that is like this. I have created one button and it has no click event handler on the server side. But it has one on the client side.
protected void Page_Load(object sender, EventArgs e)
{
Button ButtonPull = new Button();
ButtonPull.Text = "Pull";
ButtonPull.ID = "Button1";
ButtonPull.ControlStyle.CssClass = "btn btn-default";
this.Form.Controls.Add(ButtonPull);
// You can pass anything you want to the server. Here I am passing 1111
// You can pass things from the client side as well. Whole JSON objects as well
ButtonPull.OnClientClick = "callServer(1111);return false;"; // return false so button does not postback
}
I have also added this method to my page's code behind. This is a web method which receives an id as int and appends it to a string and returns that string to the client.
[WebMethod]
[ScriptMethod(UseHttpGet = true,
ResponseFormat = ResponseFormat.Json, XmlSerializeString = false)]
public static string GetStuffFromServer(int id)
{
return "Works like a charm! And id is " + id ;
}
And finally added this to my view. When the button is clicked on the client side, it will call this function and pass 1111 as we instructed it above when we created the button. Inside this function we are using jQuery ajax call to call the server method GetSuffFromServer. If all goes well the server will return and we will go into success here and alert the data returned from the server. Again, the server can return anything needed. And this method can send anything needed to the server.
<script>
function callServer(id) {
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: "default.aspx/GetStuffFromServer?id=" + id,
success: function (data)
{
alert(data.d);
},
error: function (data) { alert(data);}
});
}
</script>
One last thing in App_Start folder's RouteConfig.cs file change this line:
settings.AutoRedirectMode = RedirectMode.Permanent;
to this:
settings.AutoRedirectMode = RedirectMode.Off;
This change is because I am using a friendly url when calling the web method: default.aspx/GetStuffFromServer?id=
Iam trying to send some JSON data to the server using jquery ajax call. It doesn't seem like the data is posting as when i try to parse it in the code-behind file it throws errors. Searched around but the answers didn't help solve my problem. Any guidance would be appreciated.
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<script type="text/javascript">
$.ajax({
url: 'Default2.aspx',
type: 'post',
async: false,
contentType: 'application/json; charset=utf-8',
//data: "'"+batchtable+"'",
data: JSON.stringify({"a":"1", "b": "2"}),
dataType: 'json',
processData: false,
success: function (result) {
alert('success');
},
error: function (result) {
alert('failed');
}
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</div>
</form>
</body>
</html>
And here is the .cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Diagnostics;
using System.Web.Script.Serialization;
public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
var jsonString = String.Empty;
HttpContext context = HttpContext.Current;
context.Request.InputStream.Position = 0;
using (var inputStream = new StreamReader(context.Request.InputStream))
{
jsonString = inputStream.ReadToEnd();
}
RootObject userinput = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<RootObject>(jsonString);
}
}
public class RootObject
{
public string a { get; set; }
public string b { get; set; }
}
The error message I get is:
Invalid JSON primitive: __VIEWSTATE.
for ajax call don't call from server side event.you need to call from javascript/jquery.
you need to define a serverside webmethod and you can call that method from the jquery/javascript. here is a demo. works fine. might be helpful for you.
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$("#btnResult").click(function () {
var name = $("#txtNameTextBox").val();
$.ajax({
type: "POST",
url: "Default.aspx/GetDate",
data: "{name:'" + name + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
//alert(data.d);
$("#Result").text(data.d);
var val = data.d;
val = val.split("~");
var name = val[0];
var time = val[1];
var date = val[2];
var tempdate = date.split(":");
var finaldate = tempdate[1];
$("#txtDateToDisplay").val(finaldate);
$("#txtDateToDisplay2").val(finaldate);
},
error: function () { alert(arguments[2]); }
});
});
});
</script>
here is HTML
<h2>
Call Server side Function From JaxaScript AJAX Call ASP.NET!
</h2>
<br />
<br />
<div>
Name : <input type="text" id="txtNameTextBox" /><br/><br/>
Date : <input type="text" id="txtDateToDisplay" /><br/><br/>
Date : <input type="text" id="txtDateToDisplay2" />
<br />
<br />
<p id="Result">Message : </p>
<input type="button" id="btnResult" value="Click here for the time"/>
</div>
And here your server side code
/// <summary>
/// ===========================================
/// This is the WebMethod where ajax call happens.
//=============================================
/// </summary>
/// <param name="name">the data sent from ajax call
/// - here a string only(name of a user)</param>
/// <returns>a string with json format</returns>
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static string GetDate(string name)
{
if (name == "")
{
return "No Parcel Available";
}
else
{
name = "Name : " + name + "~" +
"Current Time : " + DateTime.Now.ToLongTimeString()
+ "~" + "Date : " + DateTime.Now.ToShortDateString();
}
return name;
}
Hope it will help you.
You need to use JavaScript/jQuery to call a server-side endpoint. ASP.NET AJAX Page Methods provide web methods that are hosted inside of a page, but are static and are not part of the page instance, so you can call them asynchronously via your client-side script, like this:
Markup:
<div id="Results"></div>
$(document).ready(function() {
$.ajax({
type: "POST",
url: "YourPage.aspx/GetGreeting",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(result) {
// Put greeting into DIV
$('#Results').text(result.d);
}
});
});
Code-behind:
[WebMethod]
public static string GetGreeting()
{
return "Hello world!";
}
Note: The above example uses the client (via jQuery) to ask the server for a greeting (string), which is JSON-encoded automatically by the ASP.NET AJAX Page Method. The result is then processed by the success handler of the jQuery .ajax() function and the actual string value is pulled out of the .d reference in the returned JSON object.
I have a asp .net web page and a button in it. I'm calling an ajax method in the button click event as follows
$("#btnTest").click(function () {
$.ajax({
type: 'POST',
url: 'test2.aspx',
success: function (data) {
alert( data);
},
error: function (data) {
alert("In error ");
}
});
});
In success part alert( data) Im getting the html code of the page test2.aspx (which one I have given in ajax url).
In test2.aspx.cs code is given as below
protected void Page_Load(object sender, EventArgs e)
{
jsonTest();
}
public List<string> jsonTest()
{
List<string> list = new List<string>();
list.Add("aa");
list.Add("bb");
list.Add("cc");
return list;
}
Why this data in 'list' is not coming as response data in ajax?
Try Response.Write() method for that purpose
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("data to be returned");
}
Or try to write static webmethods in aspx page. Those methods can be call from ajax
You cannot return data from aspx to ajax. try this
HttpContext.Current.Response.Write(list);
HttpContext.Current.Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();
HttpContext.Current.Response.SuppressContent = true;
This will help to solve your problem.
You can't call a normal page method from jQuery.
You need to create a web-method to access that from jQuery.
Here is a good link regarding how to call a page method
http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/
Use like this..
$("#btnTest").click(function () {
$.ajax({
type: 'POST',
url: 'test2.aspx',
success: function (data) {
alert( data.d[0]);
alert( data.d[1]);
alert( data.d[2]);
},
error: function (data) {
alert("In error ");
}
});
});
Is there a way to load ascx file by jQuery?
UPDATE:
thanks to #Emmett and #Yads. I'm using a handler with the following jQuery ajax code:
jQuery.ajax({
type: "POST", //GET
url: "Foo.ashx",
data: '{}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response)
{
jQuery('#controlload').append(response.d); // or response
},
error: function ()
{
jQuery('#controlload').append('error');
}
});
but I get an error. Is my code wrong?
Another Update :
I am using
error: function (xhr, ajaxOptions, thrownError)
{
jQuery('#controlload').append(thrownError);
}
and this is what i get :
Invalid JSON:
Test =>(this test is label inside my ascx)
and my ascx file after Error!!!
Another Update :
my ascx file is somthing like this:
<asp:DropDownList ID="ddl" runat="server" AutoPostBack="true">
<asp:ListItem>1</asp:ListItem>
<asp:ListItem>2</asp:ListItem>
</asp:DropDownList>
<asp:Label ID="Label1" runat="server">Test</asp:Label>
but when calling ajax i get this error in asp: :(
Control 'ctl00_ddl' of type 'DropDownList' must be placed inside a form tag with runat=server.
thanks to #Yads. but his solution only work with html tag.
Building off Emmett's solution
public class FooHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/html";
context.Response.Write(RenderPartialToString("Foo.ascx"));
}
private string RenderPartialToString(string controlName)
{
Page page = new Page();
Control control = page.LoadControl(controlName);
page.Controls.Add(control);
StringWriter writer = new StringWriter();
HttpContext.Current.Server.Execute(page, writer, false);
return writer.ToString();
}
public bool IsReusable
{
get
{
return false;
}
}
}
Use the following jquery request
jQuery.ajax({
type: "POST", //GET
url: "Foo.ashx",
dataType: "html",
success: function (response)
{
jQuery('#controlload').append(response); // or response
},
error: function ()
{
jQuery('#controlload').append('error');
}
});
public ActionResult Foo()
{
return new ContentResult
{
Content = RenderPartialToString("Foo.ascx", null),
ContentType = "text/html"
};
}
//http://www.klopfenstein.net/lorenz.aspx/render-partial-view-to-string-asp-net-mvc-benchmark
public static string RenderPartialToString(string controlName, ViewDataDictionary viewData)
{
ViewPage vp = new ViewPage();
vp.ViewData = viewData;
Control control = vp.LoadControl(controlName);
vp.Controls.Add(control);
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
using (HtmlTextWriter tw = new HtmlTextWriter(sw))
{
vp.RenderControl(tw);
}
}
return sb.ToString();
}
*.ascx files are rendered on the server side (inside of an *.aspx page), not the client side (where JavaScript is executed).
One option might be to create a blank *.aspx, put the user control on the *.aspx page, and then get that page via jQuery and dump the result on the page.
Edit
Based on your comment, I have another suggestion:
If you're developing a CMS style application, you should build your *.ascx controls so that they are compatible with the ASP.NET AJAX Toolkit. That will allow the users to add content to the page without doing a full refresh.
If you really want to make things nice for the user, you should check out Web Parts and ASP.NET AJAX as Web Parts were really designed so that users could customize the content on their pages.
I have a custom ASP.NET solution deployed to the ISV directory of an MS Dynamics CRM 4.0 application. We have created a custom entity, whose data entry requires more dynamism than is possible through the form builder within CRM. To accomplish this, we have created an ASP.NET form surfaced through an IFRAME on the entity's main form.
Here is how the saving functionality is currently laid out:
There is an ASP.NET button control on the page that saves the entity when clicked. This button is hidden by CSS.
The button click event is triggered from the CRM OnSave javascript event.
The event fires and the entity is saved.
Here are the issues:
When the app pool is recycled, the first save (or few) may:
not save
be delayed (ie. the interface doesn't show an update, until the page has been refreshed after a few sec)
Save and Close/New may not save
For issue 1.1 and 2, what seems to be happening is that while the save event is fired for the custom ASP.NET page, the browser has moved on/refreshed the page, invalidating the request to the server. This results in the save not actually completing.
Right now, this is mitigated with a kludge javascript delay loop for a few seconds after calling the button save event, inside the entity OnSave event.
Is there any way to have the OnSave event wait for a callback from the IFRAME?
The solution that I've implemented (very recently) to overcome the problem is a little complicated, but let me try to explain:
Essentially - On the page with the iFrame, you're going to track (in Session) the save event and expose the results through a WebMethod that the CRM page will call (using the jquery .ajax() functionality)
Best way to explain is with sample code (Just create a new Website Project with Default.aspx & IFramePage.aspx):
IFramePage.aspx ->
<script type="text/javascript">
SaveStuff = function() {
__doPostBack('SaveButton', '');
}
</script>
Hello - I am an iFrame!<br />
<asp:linkbutton id="SaveButton" runat="server" style="display:none;" onclick="SaveButton_Click" text="Save" />
<asp:hiddenfield id="RandomGuidHiddenField" runat="server" />
</div>
IFramePage.aspx.cs ->
public static object locker = new object();
/// <summary>
/// Gets the statuses.
/// </summary>
/// <value>The statuses.</value>
public static Dictionary<Guid, bool> Statuses
{
get
{
lock (locker)
{
if (HttpContext.Current.Session["RandomGuid"] == null)
{
HttpContext.Current.Session["RandomGuid"] = new Dictionary<Guid, bool>();
}
return (Dictionary<Guid, bool>) HttpContext.Current.Session["RandomGuid"];
}
}
}
[WebMethod]
public static bool CheckSaveComplete(string randomGuid)
{
var currentGuid = new Guid(randomGuid);
var originalTime = DateTime.Now;
if (!Statuses.ContainsKey(currentGuid))
{
Statuses.Add(currentGuid, false);
}
while (!Statuses[currentGuid])
{
if (DateTime.Now.Subtract(originalTime) > new TimeSpan(0, 0, 0, 1))
{
return false;
}
Thread.Sleep(1000);
}
return true;
}
/// <summary>
/// Handles the Load event of the Page control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
this.RandomGuidHiddenField.Value = Guid.NewGuid().ToString();
}
}
/// <summary>
/// Handles the Click event of the SaveButton control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void SaveButton_Click(object sender, EventArgs e)
{
var randomGuid = new Guid(this.RandomGuidHiddenField.Value);
if (!Statuses.ContainsKey(randomGuid))
{
Statuses.Add(randomGuid, false);
}
Thread.Sleep(10000);
Statuses[randomGuid] = true;
}
In my Default.aspx page (to simulate the CRM Form Entity page) ->
<script type="text/javascript">
function OnSave() {
var saveResult = false;
var randomGuid = window.frames[$("#daIframe")[0].id].$("input[id$=RandomGuidHiddenField]").val();
window.frames[$("#daIframe")[0].id].SaveStuff();
$.ajax(
{
async: false,
type: "POST",
url: "IFramePage.aspx/CheckSaveComplete",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: '{"randomGuid" : "' + randomGuid + '"}',
success: function(response) {
if (response.d === true) {
alert(response.d);
saveResult = true;
}
}
}
);
if (saveResult !== true) {
alert("Oh No!");
}
else {
alert("way to go!");
}
}
</script>
<iframe name="daIframe" id="daIframe" src="IFramePage.aspx"></iframe>
<asp:textbox id="lsc_paymentinfo" runat="server" text="1000" /><br />
<input type="button" value="Save" onclick="OnSave();" />
Let me know if you have any questions!
My preferred method of handling the saving of values in an iframe is via webservice. Have the CRM form call a function on your iframe that collects all of the fields and synchronously posts them. When the webservice returns a response and your save function returns, the CRM form will then perform its save.
Here's what your save method on your iframe might look like, using jQuery:
function save() {
var saveResult = false;
$.ajax({
async: false,
type: "POST",
url: "/YourWebservice.asmx/SaveIframeValues",
contentType: 'application/json; charset=utf-8',
dataType: "json"
data: '{ paramname : "paramvalue" }',
success: function(response) {
if (response.d === true) // assuming your webservice returns true upon success
{
saveResult = true;
}
}
});
if (saveResult !== true) {
// alert user, perhaps
// and stop the CRM form from saving
event.returnValue = false;
return false;
} else {
// iframe save was successful, time for a nap
}
}
One thing that would help is to increase the app pool timeout in IIS. Its default is 20 minutes so if nobody uses your IFrame for 20 minutes, it will recycle the app pool and result in a long delay the next time it's fired up.
One solution in that case is to hook on the IFrame State or Events, and continue the CRM save action only when the IFrame is reloaded after the postback. In that way, if the custom app fails or is slow, you can notify the user and cancel the save process.