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 !).
Related
I'm a PHP/Rails developer and have inherited an ASP.NET application (and its maintenance). So I have a few simple questions.
1.) What's the makeup of a typical rendered(compiled?) HTML page in ASP.NET. That is, when a request is made what happens from the initial request to the time the HTML is displayed in the browser? I'm assuming some templates are combined and finally rendered but I'd like a more in-depth answer.
2.) I've been asked to remove a link from a Login form which is an aspx page. Looking at the aspx page itself it has an inherit statement, a link to the codebehind file, and links some other resources. Where do I actually remove the link from the Login page/template at? I've so far been unable to find exactly where the link is written so that I can remove it or comment it out.
Thank you!
That is, when a request is made what happens from the initial request
to the time the HTML is displayed in the browser?
I'd start learning about the ASP.Net Page Life Cycle.
I've so far been unable to find exactly where the link is written so
that I can remove it or comment it out.
I wouldn't do anything until you have at least a decent grasp of how ASP.Net works. It would be good to run through a few tutorials. ASP.Net has a nice Get Started section.
What's the makeup of a typical rendered(compiled?)
To give you a very simple instructions (trying) to help you fast understand it:
There is a page with the aspx tags, the asp.net is running the code behind and fill this tags with data.
After the filling with data on code behind, the asp.net is "running" the full page and if you have <% %> inside the aspx page, addition code runs that exist inside that.
This is a simple example:
public partial class Dokimes_StackOverFlow_Diafora : System.Web.UI.Page
{
public string cRenderMeAlso = "test";
protected void Page_Load(object sender, EventArgs e)
{
txtText.Text = "One Test";
}
}
<form id="form1" runat="server">
This will fill when the page is prepared
<asp:Literal runat="server" ID="txtText"></asp:Literal>
<br />
This will be render as the page reads out to send it to the browser
as php do
<%=cRenderMeAlso%>
</form>
Now in the place of the Literal control, you can have a full custom render control, that maybe a new complex part of a page with his elements and render.
Each page, master page, user control have a cycle of calls to help first pass all from Init() and prepare them, then pass all from Load(), and the other stage, giving the ability to initialize them in parallel - together.
Now, on PostBack the page have been keep some information's on ViewState that are posted together with the rest post data, and the Code behind use all that data to fill the controls. Also its fires on code behind any click event you have initialize on buttons and you can run some code there to do your work.
I've been asked to remove a link from a Login form
if you can not find that link is maybe on the standard login form that asp.net gives, the solution to that is to render the full template of the form, and remove it from there - but because there is the case to break the Login form, is better to not remove it and just hide it - because if you remove it and the code behind ask for it, it will throw an error - I mean for the standard asp.net forms login code that is part of the asp.net.
So if this is the case, render the login control as template (from design mode, do that on properties), see the link you search and ether make on code behind Link.Visible = false, ether remove it and delete on code behind all the reference on it.
We have a web control that we want to render into a div on the already loaded page. This needs to happen when the user clicks on a hyperlink in the menu.
The web control has some javascript files that are added to it dynamically in the C# code.
We also arent using aspx files, and want to load the web control onto a normal html page.
Please let me know what would be the best way to do this, or direct me to an article as I'm struggling to find anything useful on the web. any help is appreciated.
You can render your control dynamically in a string, send the string back and place it inside your div. Using ajax you call the code behind to render the control and return you the results.
// load the control
var oCConrol = Page.LoadControl("CustomControl.ascx");
// here you need to run some initialization of your control
// because the page_load is not loading now.
// a string writer to write on it
using(TextWriter stringWriter = new StringWriter())
{
// a html writer
using(HtmlTextWriter renderOnMe = new HtmlTextWriter(stringWriter))
{
// now render the control inside the htm writer
oCConrol.RenderControl(renderOnMe);
// here is your control rendered output.
strBuild = stringWriter.ToString();
}
}
Alternative you can get the same results by just make an extra empty aspx page with only your control inside and call it using Ajax. The result will be again the control
The javascript how ever is dificult and can not go with the control. You can not send text back and then make it run as javascript inside the control, this must be done separated.
I have done something similar by creating a separate, standalone .aspx page and Jquery ajax. Call to the .aspx page using Jquery ajax and return all the rendered HTML from that page via the ajax response.
As far as I know, there is not any way to render a web control outside the context of a .aspx page.
I need to make a full asp.net webform with Server Control. I Wonder how to do this?
There is a class called Page in .Net but I don't know how to work with it.
A Page or WebForm must have a URL so from other pages can be accessible. Who knows this?
Your problem is to generate your page without using aspx, am I right ?
If you want your page to be accessible from your WebServer, you will need the .aspx file, even if you completely generate your page by code.
To create your page, you create a class who inherits from the Page class, and you add your server controls to it.
public class TestCodePage : Page
{
public TestCodePage()
{
HtmlForm form = new HtmlForm();
LiteralControl l = new LiteralControl("I write a text in my form");
form.Controls.Add(l);
this.Controls.Add(form);
}
}
In order to have an url for this page, you just need to create an aspx page with this content :
<%# Page Inherits="MyWebApp.TestCodePage" %>
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.
I have a page with the following caching defined:
<%# OutputCache Duration="60" VaryByParam="None" %>
I have a user control inside that page that i don't want cached. How can I turn it off just for that control?
Option One
Use the Substitution control or API on your page. this enables you to cache everything on your page except the part contained within the substitution control.
http://msdn.microsoft.com/en-us/library/ms227429.aspx
One nice way to use this is to implement your control as a simple server control which renders the html as a string, but does so in the context of the page (that is with the correct Client IDs). Scott Guthrie has a really nice example of how this works. Works nicely with AJAX calls too by the way...
http://weblogs.asp.net/scottgu/archive/2006/10/22/Tip_2F00_Trick_3A00_-Cool-UI-Templating-Technique-to-use-with-ASP.NET-AJAX-for-non_2D00_UpdatePanel-scenarios.aspx
Excerpt from Scott Gu's article...
[WebMethod]
public string GetCustomersByCountry(string country)
{
CustomerCollection customers = DataContext.GetCustomersByCountry(country);
if (customers.Count > 0)
//RenderView returns the rendered HTML in the context of the callback
return ViewManager.RenderView("customers.ascx", customers);
else
return ViewManager.RenderView("nocustomersfound.ascx");
}
Option Two
Render the dynamic control via an AJAX call on the page load. This way, you can safely cache the entire page (including the AJAX call) and it is only the rendered result of the call that changes between pages.