I'm having the same problem I had yesterday... The solution Aristos provided helped solve the problem, but I have other places sending updatepanel postbacks causing the same problem.
When an update panel is updated and another request for an update is called before it has a chance to render the first updates, the entire page refreshes instead of just the update panel.
I used fiddler to see what was going on and here's what happens... If I wait for the request to return before doing another request I get this:
21443|updatePanel|dnn_ctr1107_CRM_SalesTool_LeadsUpdatePanel|
But if I don't wait, I get this:
66|pageRedirect||http://mysite.com/salesdashboard.aspx|
The code from the previous question is still the same except I added UpdateMode="Conditional" to the update panel.
Any ideas? Or is the only solution to this making sure that 2+ updates for any number of update panels (as long as they're on the same page) never happen?
Thanks,
Matt
Maybe microsoft automatic ajax can not handle 2 request at the same time because he needs to know what is the post back every time, so probably if you click when he wait for a return, then he knows that the post back, has change, so he by pass ajax to be soure for correct return.
I can think 2 ways. One way is to make it by your self using jQuery and ajax and avoid UpdatePanel.
Second way, is to block the clicks when you wait for the return, or make a mechanism to place the request, the one after the other.
This code can help you know when you block the input and when you release it, or do what ever you think.
$(document).ready(function() {
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
});
function InitializeRequest(sender, args) {
LastIdCaller = args.get_postBackElement().id;
}
function EndRequest(sender, args) {
}
I could be wrong, but if I'm right then you can't do multiple ajax request if you are using asp.net WebForms. In asp.net WebForms there is only one Form element on a page. Multiple ajax requests on the same page require multiple form elements for each. Html is designed to post back inside a form element and the mechanism that handles said postback is the form, it's the container. Only one can post back at a time. So because Asp.Net WebForms only has one form element per page, you can only do 1 ajax postback per page.
Optionally, you can create generic ASHX Http Handlers to do your form logic and use JQuery Ajax to post back to the Generic Http Handlers. In which case you can do as many of those at a time as you want.
Generally I use ASHX handler's any time I need to serve images that change, like on the fly imaging. I also use them for large data outputs. E.g. the ASHX handler returns a big dump of JSON. I do an Ajax Postback to the ASHX handler to get a set of data in JSON and append it to a table etc and I call the ASHX handler repeatedly on a timer to get new Data as it comes in (say a 5 min timer) etc.
If you gave some more context on what your trying to do I might be able to provide you with alternative solutions.
Edit: I looked at your other post you linked and I think an ASHX handler would serve you well. You can design the ASHX handler to return your Search Data in JSON. You can use Request varaibles in the ASHX handler and you can send post data to the ASHX Handler with JQuery.Ajax.
You should be able to fire off multiple requests each with it's own Success Function. Then you would need to write the javascript in such a way that as it's processing the JSON data from the ashx handler it can merge with other requests as they finish.
Related
I have a listview with 250 rows and 4 columns in my ASP.Net 4.0/C# application. The Rendered page size (from Trace) is 650,000 Bytes. The entire listview is in an update panel.
The listview facilitates view/add/edit/delete operations on the listview records.
Every POSTBACK action (i.e. edit click, delete click) causes a POSTBACK request of size 112,000 Bytes and an AJAX Response of ~650,000 Bytes.
The listview gets the data from a declarative data source (SQLDataSource) on the page. And the listview is bound on each round trip.
I want to reduce the data going back and forth in every call because on a slow connection, these AJAX calls take 2-3 minutes to complete.
What I have tried -
Removed the update panel over the entire listview and added an update panel over each:
ItemTemplate contents
AlternateItem Template contents
Edit Template contents
Insert Template contents
I was hoping that with the template in each row, it would reduce the size of the AJAX response since only the HTML for the update panel would come back. Unfortunately, it does not seem to work that way.
Any inputs on how the problem in my case can be solved?
Thanks in advance for looking this up.
The problem with an UpdatePanel is that you are not using real AJAX. Instead ASP.NET uses some really clever hacks to create the illusion of a partial page update. On the background, your whole page life cycle is executed. This also means that your complete ViewState is send back and forth.
If you want a faster experience, you should not use UpdatePanels. Instead, use plain HTML controls (preferably not even server controls) and use JavaScript and a server side webservice (such as WebAPI or a WCF service) to respond to the client side requests.
Those requests and response will only contain some JSON data and no markup. Your data can be kept to a minimum. If for example, a user removes a row, you only have to send the Id of the row to your service and it will return success or failure. The client will use JavaScript and maybe something like KnockoutJS to render the result. This will give you minimal overhead and a better performance.
The best possible way to do this is to not use the ASP.NET user controls and instead do this cleanly using JavaScript, JSON, HTML and a server side web service/http handler
That way you don't have to send large HTML responses from the server to client. You can also control when need to refresh and rebind your data.
I bet the whole size issue has to do ViewState. The reason being that on every postback, even if it's an AJAX postback the ViewState travels with it on every request. The only thing you can do, without making any changes, is to enable compression on the IIS side. This, at least, will send the response compressed and the browser will take care of decompressing it.
The best approach is not to use UpdatePanel and ScriptManagers at all and instead make AJAX requests using jQuery (or whatever framework you prefer) by invoking a WCF Web service. This will not trigger the full page lifecycle and will not send the ViewState on every request.
I'm retro-fitting a .aspx page with AJAX functionality (using VB, not C#). The codebehind populates the page with data pulled from a web-service. The page has two panels that are populted (with different data, of course) in this way. On a full page refresh, one or both panels might need to be populated. But populating Panel 2 can take a long time, and I need to be able to update panel 1 without refreshing Panel 2. Hence the need for AJAX (right?)
The solution I've come up with still has the old .aspx page with .aspx.vb codebehind, but introduces a Generic Handler (.ashx) page into the mix. Those first two components do the work on the user's first visit or on a full page refresh, but when AJAX is invoked, the request is handled by the .ashx page.
First question: Is this sound architecture? I haven't found a situation online quite like mine. Originally, I wanted to make the .aspx page into the AJAX handler by having the codebehind implement IHttpRequest, and then providing "ProcessRequest" and "IsReusable" methods, but I found I couldn't separate a regular visit to the page from an AJAX request, so my AJAX handlers took over even on the first visit to the page. Second question: Am I right to think that this approach (making the .aspx page do double-duty as the AJAX handler) will never work? Is it impossible to tell whether we're getting a full-page request or a partial-page (AJAX) request?
If the architecture is good, then I need to dynamically generate a lot of HTML in the .ashx file, right? If that is right, should I send HTML back to the client, or should I encode it in some way? I've heard of JSON encryption, but haven't figured out how to use it yet. So, Third question: Is "context.Response.Write" the only pipeline for sending data back to the client? And, if so, should I send back HTML or some kind of JSON-encoded objects?
Thanks in advance.
It sounds as if the page requires some AJAX functionality added to the UI.
Suggest using an UpdatePanel for each web form element that needs to have AJAXy refresh
functionality. That'll save you from having to refactor a bunch of code, and introduce a whole lot of HTML creation on your .ashx.
It'll be more maintainable over the long run, and require a shorter development cycle.
As pointed out by others, UpdatePanel would be a easier way - but you need to use multiple update panels with UpdateMode property set as conditional. Then you can trigger the update-panel refresh using any button on the page (see AsyncPostBackTrigger) or even using java-script (see this & this). On the server side, you may decide what has triggered the partial post-back and act accordingly by bypassing certain code if not needed.
You can also go with your approach - trick here is to capture the page output using HttpServerUtility.Execute in your ashx and write it back into the response (see this article where this trick has been used to capture user control output). Only limitation with this approach is that you can only simulate GET requests to your page and so you may have to change your page to accept parameters via query string. Personally, I will suggest that you create a user control that accept parameters via method/properties and will generate necessary output and then use the control on your page and in ashx (by dynmaically loading it in a temperory page - see this article).
EDIT: I am using jquery to illustrate how to do it from grid-row-view.
$(document).ready(function() {
$("tr.ajax-grid-row").click(function() {
$("#hidden-field-id").val($(this).find(".row-id").val()); // fill hidden filed
$("#hidden-button-id").click(); // simulate button click
});
});
You can place above script in the head element in markup - it is assuming that you have decorated each grid-row-view with css class "ajax-grid-row" and each row will have hidden field decorated with css class "row-id" to store row identifier or the value that you want to pass to server for that row. You can also use cell (but then you need to use innerHTML to get the value per row). "hidden-field-id" and "hidden-button-id" are client ids for hidden field and submit button - you should use Control.ClientID to get actual control ids if those are server controls.
JSON is not for that purpose, it is to pass objects serialized with a nice light weight notation, is you need to stream dinamically generated html using ashx, response.Write is what you have. You may want to take a look at MVC
Or you could use jquery if it's just html, the simpliest would be the load function, or you can look into Ajax with jquery. Since the ashx can be served as any resource it can be used in the load function.
I agree with #p.campbell and #R0MANARMY here. UpdatePanel could be the easiest approach here.
But then like me, if you don't want to go the UpdatePanel route, I don't see anything wrong with your approach. However, generating the html dynamically (entirely) at the back end is not a route I'll personally prefer (for the maintainence reasons). I'd rather prefer implementing a solution that will keep the design separate from the data.
I have a requirement to call a save method, that persists a model/object in the session, when the user leaves the page.
The page has various links that do not raise a postback but just perform a redirect. Are there any ASP.Net page life cycle methods I can hook into to perform the save without requiring a postback?
One solution could be to perform an asynchronous POST request (without waiting for a response) when the window is being unloaded:
An example using jQuery:
$(window).unload(function() {
$.post(location.href, $(document.forms[0]).serialize());
});
Although you will probably need to use a slightly different method for Chrome (found on jQuery forums):
It looks like the only way to get the
Ajax request to go through in Chrome
is to use the non-standard event
onbeforeunload. Chrome evidently
doesn't wait long enough to send the
Ajax request using onunload. It does
however wait for alerts...
Well that depends.
If you need to save values when the person leaves the page, then thats kinda hard.
What you can do, is to wrap all your links in some jquery, that says like:
Issue a Ajax Call, to AjaxSave.aspx, then it is completed, then window.location to the links href attribute.
BUT, that will only work if the person clicks on your links, not if the person just closes the browser or something.
You can also take the route to just save the stuff offen, so every time the person issues a post back, you just put the stuff in session. But that will mean that values changed from the last postback to the navigating away from the page is lost - don't know if that is an issue.
The last thing is to do like StackOverflow is doing. If you are editing stuff, it will show a warning when you leave the page, and then you have to click okay, to navigate away from the site.
We have a method on an asp.net page that is called on a button click. The problem is that the method take a long time to process. I've been asked to have the page call the method (or call the postback) and then display the jquery.ui dialog which will let the user know that this process could take a long time. I'm looking at serializing the asp.net form and doing a $.post() but to be honest I'm completely stuck on whether this will even work and how I can prevent the actual postback from happening and just displaying the dialog. Has anyone had any experience with doing this that can give me some pointers?
I found this http://dotnet.dzone.com/news/eliminating-postbacks-setting- but I'm not sure if it's a bit OTT. The article is a little long winded.
Hope someone can help.
That would be easier if you can use an UpdatePanel (which basically boils down to ASP.NET's way of doing what you're considering with the $.post(), but automatically gets the ASP.NET specific stuff right).
Then, you can do something simple like this: http://encosia.com/2008/10/04/using-jquery-to-enhance-aspnet-ajax-progress-indication/
You can send a post request through javascript (AJAX) without using asp.net's ajax framework. So in other words do it manually. Ajax would be perfect in this case, because you are trying to show loading indicators on the front-end while you are waiting for a response from the server.
To do this, take the logic out of your button_click method and put it in a separate page (text.aspx see below). Then you can call that page like this (using JQuery):
$('#ProgressIndicator').show();
$.post("test.aspx", function(data){
alert("Data Loaded: " + data);
$('#ProgressIndicator').hide();
});
If you can't use JQuery in your project, see: AJAX
How do you call a Javascript function from an ASPX control event?
Specifically, I want to call the function from the SelectedIndexChanged event of a DropDownList.
I get a little nervous whenever I see this kind of question, because nine times out of ten it means the asker doesn't really understand what's going on.
When your SelectedIndexChanged event fires on the server, it fires as part of a full postback. That means that for that code to run, the entire rest of your page's load code also had to run.
More than that, the code runs as the result of a new http request from the browser. As far as the browser is concerned, an entirely new page is coming back in the result. The old page, and the old DOM, are discarded. So at the time your SelectedIndexChanged event code is running, the javascript function you want to call doesn't even exist in the browser.
So what to do instead? You have a few options:
Change the page so the control doesn't post back to the server at all. Detect the change entirely in javascript at the client. This is my preferred option because it avoids odd onload scripts in the browser page and it saves work for your server. The down side is that it makes your page dependent on javascript, but that's not really a big deal because if javascript is disabled this was doomed from the beginning.
Set your desired javascript to run onload in the SelectedIndexChanged event using the ClientScript.SetStartupScript().
Apply the expected results of your javascript to the server-model of the page. This has the advantage of working even when javascript is turned off (accessibility), but at the cost of doing much more work on the server, spending more time reasoning about the logical state of your page, and possibly needing to duplicate client-side and server-side logic. Also, this event depends on javascript anyway: if javascript is disabled it won't fire.
Some combination of the first and third options are also possible, such that it uses javascript locally if available, but posts back to the server if not. Personally I'd like to see better, more intuitive, support for that built into ASP.Net. But again: I'm talking about the general case. This specific event requires javascript to work at all.
As Muerte said you have to just put the javascript, or a call to it on the page from the code behind. Personally I use this:
ClientScript.RegisterClientScriptBlock("customscript", "<script>simple script here</script>")
Of you can call the function if you already have a more complex one on the page instead of the stuff I have.
You can't do it directly from an event, because ASPX control event is server side.
What you can do is emit a Javascript in the ASPX event which will call the JavaScript function when the page reloads.
For example, if in your ASPX page you have a Javascript function called "DoSomething()", in you ASPX control event, add the following:
protected void btnSubmit_Click(object sender, EventArgs e)
{
Page.ClientScript.RegisterStartupScript(this.GetType(), "myEvent", "DoSomething()", true);
}
The last boolean parameter defines that tags are added automatically.
In the code behind, attach some markup to the server side control via its attributes collection. This assumes that the function is already in a client script file that is already available to the page.
MyServerDDLControl.Attributes.Add("SelectedIndexChanged", "MyClientSideFunction();");