Using .aspx page as Ajax event handler? - asp.net

For several days now I've been messing around with Ajax calls using different combinations of javascript, ASP controls, and regular controls. I've gotten a bit of understanding about what's going on, but using ASP controls still hides too much of the machinery, and I want to have a deeper understanding. With that aim, can anyone tell me why the following setup doesn't quite work?
I have a file "Testy.aspx" with the following:
<asp:Content>
<script type="text/javascript">
// a standard home-grown Ajax javascript method
function ajaxfunction() {
var ajaxObj = getAjaxObj(); // does the usual browser-detection
if (ajaxObj) {
ajaxObj.open("GET", "Testy.aspx", true);
ajaxObj.setRequestHeader("IsAjaxRequest", "true");
ajaxObj.send();
ajaxObj.onreadystatechange = function() {
if (ajaxObj.readyState == 4) {
document.getElementById("testytext").appendChild(document.createTextNode(ajaxObj.responseText));
}
}
}
}
</script>
... other unrelated html, ASP controls, etc...
<input id="testybutton" type="button" value="baroo" onclick="ajaxfunction()" />
<div id="testytext"></div>
</asp:Content>
Meanwhile, I have a code-behind function "Testy.aspx.vb" with the following:
Partial Public Class Testy
Inherits System.Web.UI.Page
Implements System.Web.IHttpHandler
...code for an ordinary (non-Ajax) request is in the middle here...
' Now I have code for Ajax requests
Overrides Sub ProcessRequest(ByVal context As HttpContext)
If context.Request.Headers("IsAjaxRequest") = "true" Then
context.Response.ContentType = "text/plain"
context.Response.Write("Hello World!")
Else
MyBase.ProcessRequest(context)
End If
End Sub
Overloads ReadOnly Property IsReusable() As Boolean
Get
Return False
End Get
End Property
End Class
So, I hoped to make my .aspx file do double-duty both as the regular-page request handler as well as the Ajax request handler. However, when I click the button ("baroo") to generate the Ajax request, the result that ends up written back to the "testytext" div is the raw html for the entire page, as if under normal request conditions. Clearly, my attempt to override the page request by making the code-behind implement IHttpHandler and supplying an "Overrides Sub ProcessRequest" method is not working. The server is still treating the Ajax request as a normal request, and in fact my own "ProcessRequest" method is never even called.
Is it possible to build a page/handler like this? How can I intercept the incoming request from the client and respond accordingly? This is how Ajax works, right? So it must be possible.
Again, I'm deliberately doing this as an excercise to avoid the use of "magic" ASP controls like UpdatePanels, so please don't advise their use.

Setup a different file that is your generic handler and don't combine the two.
Generic Handlers (.ashx) and regular web forms (.aspx) differ in that generic handlers do NOT run all of the normal win form page processing and instead simplify things quite a bit. Generally speaking you don't want the full page model for this situation, hence the reason they should be different files.
If you really want to have the methods in your main page that you'll call via ajax, then look into the "WebMethod" attribute. However, I wouldn't go this route.

Related

calling masterpage control from static method in pages

I have a fileupload , in fileupload used onchange event , on change event use a javascript function that call a static webmethd to validate filecontent .
how can i calling masterpage control in this static function in this page
please help me this nessecery
Since the static method has no knowledge of the current System.Web.UI.Page, you might not be able to access the property you are looking for. It's hard to tell what you're trying to do without a code example.
You can try the code below, but it might not work since the view state will not be available via an async WebMethod call. View state is transmitted with each postback and a System.Web.UI.Page object is instantiated using the viewstate. Since you aren't doing a postback, view state is not available.You might have to do a full postback.
If the property is being stored in Session state or Application state you might be fine. Try
Page currentPage = HttpContext.Current.Handler as Page;
currentPage.MasterPage.MyProperty = "foo";

ASP.NET and ajax response

I have a main web page ("Base Page") that makes an ajax call (using jQuery) to the server. The server-side page ("Ajax Page") is an ASP.NET web form (no MVC in use here). Because (in this case) I'm using a GridView to render data within the ajax response, I have to include the <form runat="server"> tag.
My complaint is this--when the Base Page receives the AJAX response, it inserts it into the DOM, but because the AJAX response is comprised of HTML markup that includes a <form> tag, this sometimes results in nested html forms, which is bad.
I realize that I can use jquery to only insert a fragment of the response into the Base Page DOM--or that I could use jquery to subsequently strip out the offending <form> tag. But these feel like klunky work-arounds. Is there really no way to prevent the ASP.NET page from serving out its response with a <form> tag? I realize that the form tag is the heart of the ASP.NET webform model, but it sure makes using AJAX in ASP.NET a complicated affair--very much swimming upstream. Surely Microsoft has realized that the postback / server-side model is a thing of the past?
I also realize that Microsoft has some server-side AJAX libraries that probably address this issue--but I'd still like to know if there's a solution native to ASP.NET webforms.
Any suggestions?
You can add your GridView to a Web User Control and then render it to a string like this:
public static string ExecuteToString(this Control control)
{
Page page = new Page();
page.Controls.Add(control);
StringBuilder sb = new StringBuilder();
using (StringWriter writer = new StringWriter(sb))
{
HttpContext.Current.Server.Execute(page, writer, false);
}
return sb.ToString();
}
This means you don't need to point your ajax request to a page. You can use a web service. Query a specific method and then dynamically load the User Control, render it to a string and return the HTML. Because you put your HTML and code in a User Control you don't need to worry about stripping out form tags and you can still use all the asp controls as you would on a page.
I have no idea about the performance costs of using this method but I've been using it for a while and it seems fine to me.
Working with WebForms & AJAX for many years I can understand your frustration.
Usually when working with loading WebForm pages using jQuery AJAX, I wrap an ajax class around my page, just nested inside the form:
<html>
<head></head>
<body>
<form runat="server">
<div class="ajax">
Content here..
</div>
</form>
</body>
</html>
Then when I load the page, I call just this ajax class:
$("element").load("http://domain.com/webpage.aspx .ajax");
This means the form element isn't rendered into my page, preventing nested form issues, but your GridView can still be rendered into HTML successfully.
I was dealing with the same kind of issue, I resolved it the following way:
Response.Write("whatever content")
Response.End()
This will send ONLY what you put in "Response.Write()"... You're still free to alter headers, etc.
If your ajax server page is an aspx page(ex : ajaxpage.aspx) , you can remove the HTML makup in the ajaxpage.aspx except the first line which mentions the Page directive. So it should be something like this.
<%# Page Language="C#" CodeBehind="ajaxpage.aspx.cs" Inherits="MyProject.ajaxpage" %>
And in the code behind, you can return the data using response.Write
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("your markup to return here");
}
If it is to return some kind of (clean) HTML markup / some part of data, I am inclined to use a generic handler (ex : ajaxresponse.ashx )file instead of an aspx file and return data from that
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("<h3>Here is the Markup for UserDetails</h3>");
}
You can not use ASP.NET server controls on an ashx file. And you can not have a page to have a server control (ex : GridView ) without a form tag. It should be placed inside a form tag. Note that your server controls like gridview is going to render an HTML table markup only.
Personally if i want to get some clean & controlled HTML markup which i want to show /inject into my current page using ajax, i will use an ashx handler and write my code to output my required markup. ASHX files has performance advantages compared to a aspx file as it wont go thru the normal ASPX page life cycle ( All those events !).

In ASP.Net, How do I run code after sending page

In ASP.Net, I want to run some code (logging, other cleanup) after the page has already been sent to the user. I don't want this code to interfere with the amount of time it takes the client to receive a response. I tried placing this code in the OnUnload part of the page, but through testing (using breakpoints, or busy waiting loops) the client does not actually display the page until the code in the OnUnload is finished executing. Even though the response object is no longer available at this point, and therefore I would assume that the buffered response has been sent to the client, the client still does not display the page until the OnUnload is finished executing. The only way that seems to work at the moment is to start a new thread to do the work, and allow the OnUnload to finish immediately. However, I don't know if this is safe or not. Will the server kill the thread if it executes too long after the page is already sent out? Is there a more correct way to accomplish this?
Kibbee,
Try overriding the Page.Render method and flushing the response like so:
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.Render(writer)
Response.Flush() ' Sends all buffered output to the client
' Run some code after user gets their content
End Sub
I think at this point the response still isn't complete, but the user will get what the page has rendered before you finish running that final code.
HTH,
Mike
Unload is the last part of the ASP.NET page life cycle. See link below:
http://msdn.microsoft.com/en-us/library/ms178472.aspx
Is this something you could do with javascript or AJAX?
How about hooking into the page.Disposed event instead of the Unload event?
Depending on what you need to do an ISAPI filter can be created to do stuff at the end of the response.
You could try this solution - Best ASP.NET Background Service Implementation
Using a windows service and communicating with it through MSMQ might be a far more reliable solution and can scale up better. This will help you separate the concerns and let asp.net front end just focus on the user while the windows service focusses on the background tasks.
If you are moving to the cloud with azure, you can simply replace the asp.net front end with a web role and the windows service with a worker role and ur solution can scale seamlessly!
Here's a redneck way to do it. Have a second aspx page that does all your "clean up" post-rendering logic. Call that one 'cleanup.aspx' for example. Have your clean up code run in Page_Load of cleanup.aspx:
public partial class cleanup: System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// do logging blah blah here....
}
}
In your main aspx page, have a JavaScript function that makes an AJAX call to 'cleanup.aspx'. Make the AJAX function fire after page load. I recommend jquery, if so your code will look like this:
$(function(){
yourAJAXYFunctionName();
});
function yourAJAXYFunctionName()() {
// ajax code here
//
$.ajax({
url: "cleanup.aspx",
});
}
This way, your first page's code runs, then the page is sent to the browser. As the page renders to the client, the 2nd ASPX page is called via AJAX, which really doesn't matter to cleanup.aspx, it doesn't care how its called and its page load event is executed. Your cleanup/logging code is then ran.
Caveats: client side JavaScript is required. But really who the hell doesn't have JS running anyway? Also, your cleanup.aspx page is totally abstracted from your main page, so if you want to use any object in cleanup.aspx that originated in your first page, then you'll have to store them in session or cookies, or you can pass them as parameters in the AJAX call. That will require dynamic manipulation of the AJAX script itself, but that's not too hard.
Better i think try try{Response.End()}catch{} runcode();

AJAX+ASP.NET

As far i learned ....AJAX is used for partial page refresh (overcoming the flickering effect in the web page) ....Is there any other features in AJAX....
Technically Yes. Ajax is used for "partial page" refresh there by eliminating the complete page refresh. There are 2 main advantages
Data transfer : Data transfer (To and from the server) is less compared to the entire page refresh
Better User experience : Since the user will not be seeing a blank page it gives the user an illusion of interacting with the site.
What can be done using AJAX is an ever ending list.
Ex: Gmail uses AJAX for it email. If you are using gmail and compare it with other email providers you will know the difference.
Facebook has rich AJAX features in its site.
SO uses AJAX for comments
I think What AJAX cannot do will be easier to mention. For example
AFAIK web browsers cannot maintain the view state of the AJAX enabled website.
Some AJAX enabled websites do not render properly in mobile browsers.
Anythign more?
Your question is a bit confusing, but you can do Ajax with ASP.NET. You can do partial page refreshes with Ajax among other things using the UpdatePanel in ASP.NET. You may also want to look at jQuery for a simpler more lightweight Ajax solution.
I think you're very mistaken. If AJAX had been created only to solve the problem of partial page refresh/page flickering, it would not have revolutionized the web in the way it has.
The single biggest advantage offerred by AJAX is Client-to-Server Communication that is initiated based on some action on the client. This instantly gives us the ability to make the web much more responsive and user friendly without users having to wait for page reloads and postbacks.
I would suggest that you spend some time researching the subject. Read up on the Wiki article on AJAX.
As far as ASP.NET is concerned, AJAX integrates very well into it. Mature AJAX frameworks such as ASP.NET AJAX and Anthem.NET obfuscate much of the internal details of the XmlHttpRequest.
Ajax has let me add some great new features to my web applications with the free Ajax toolkit. See the link
Ajax Examples
They do not come with out their issues but once you learn how to use them they can really add to the the users experience in you site.
ASP.NET uses as you know UpdatePanel for partial page refresh using AJAX.
A less known feature is something .NET calls web methods. This is really AJAX calls that is not connected to the GUI part of the page. You can declare (server-side) a method as a WebMethod, and in the client side, you can call that using JavaScript.
Example:
This example shows how to get the value of a session variable. Note that the method must be Shared - which means that it does not know of any member values on the page object.
As for all ASP.NET AJAX functionality, you need to have a ScriptManager element on the page. To enable page methods, you also need to add EnablePageMethods="true" to the ScriptManager like this:
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" />
Server side code (VB):
<Services.WebMethod()> Public Shared Function GetPreviewImages() As String
Dim lPreviewImages As String = HttpContext.Current.Session("mPreviewImages")
If lPreviewImages IsNot Nothing Then
Return lPreviewImages
Else
Return ""
End If
End Function
Client side code:
//Declare the return methods:
function GetPreviewImages_Success(result, userContext, methodName) {
alert(result);
}
function GetPreviewImages_Failed(error, userContext, methodName) {
var errorMessage = 'Error in map server method ' + methodName ;
if(error !== null) errorMessage += '\n' + error.get_message();
alert(errorMessage);
}
// Call the page method:
PageMethods.GetPreviewImages(GetPreviewImages_Success, GetPreviewImages_Failed);
See also example in C#, which also includes how parameters work in the web method.

Modifying the HTML of a page before it is sent to the client

I need to catch the HTML of a ASP.NET just before it is being sent to the client in order to do last minute string manipulations on it, and then send the modified version to the client.
e.g.
The Page is loaded
Every control has been rendered correctly
The Full html of the page is ready to be transferred back to the client
Is there a way to that in ASP.NET?
You can override the Render method of your page. Then call the base implementation and supply your HtmlTextWriter object. Here is an example
protected override void Render(HtmlTextWriter writer)
{
StringWriter output = new StringWriter();
base.Render(new HtmlTextWriter(output));
//This is the rendered HTML of your page. Feel free to manipulate it.
string outputAsString = output.ToString();
writer.Write(outputAsString);
}
You can use a HTTPModule to change the html. Here is a sample.
Using the answer of Atanas Korchev for some days, I discovered that I get JavaScript errors similar to:
"The message received from the server could not be parsed"
When using this in conjunction with an ASP.NET Ajax UpdatePanel control. The reason is described in this blog post.
Basically the UpdatePanel seems to be critical about the exact length of the rendered string being constant. I.e. if you change the string and keep the length, it succeeds, if you change the text so that the string length changes, the above JavaScript error occurs.
My not-perfect-but-working solution was to assume the UpdatePanel always does a POST and filter that away:
protected override void Render(HtmlTextWriter writer)
{
if (IsPostBack || IsCallback)
{
base.Render(writer);
}
else
{
using (var output = new StringWriter())
{
base.Render(new HtmlTextWriter(output));
var outputAsString = output.ToString();
outputAsString = doSomeManipulation(outputAsString);
writer.Write(outputAsString);
}
}
}
This works in my scenario but has some drawbacks that may not work for your scenario:
Upon postbacks, no strings are changed.
The string that the user sees therefore is the unmanipulated one
The UpdatePanel may fire for NON-postbacks, too.
Still, I hope this helps others who discover a similar issue. Also, see this article discussing UpdatePanel and Page.Render in more details.
Take a look at the sequence of events in the ASP.NET page's lifecycle. Here's one page that lists the events. It's possible you could find an event to handle that's late enough in the page's lifecycle to make your changes, but still get those changes rendered.
If not, you could always write an HttpModule that processes the HTTP response after the page itself has finished rendering.
Obviously it will be much more efficient if you can coax the desired markup out of ASP.Net in the first place.
With that in mind, have you considered using Control Adapters? They will allow you to over-ride how each of your controls render in the first place, rather than having to modify the string later.
I don't think there is a specific event from the page that you can hook into; here is the ASP.Net lifecycle: http://msdn.microsoft.com/en-us/library/ms178472.aspx
You may want to consider hooking into the prerender event to 'adjust' the values of the controls, or perform some client side edits/callbacks.

Resources