I'm trying to take an开发者_如何学Python existing bunch of code that was previously on a full .aspx page, and do the same stuff in a .ashx handler.
The code created an HtmlTable object, added rows and cells to those rows, then added that html table the .aspx's controls collection, then added it to a div that was already on the page.
I am trying to keep the code in tact but instead of putting the control into a div, actually generate the html and I'll return that in a big chunk of text that can be called via AJAX client-side.
HtmlTable errors out when I try to use the InnerHtml property (says it isn't supported), and when I try RenderControl, after making first a TextWriter and next an HtmlTextWriter object, I get the error that Page cannot be null.
Has anyone done this before? Any suggestions?
*Most recent is above.
OK, even after Matt's update there is a workaround ;)
Firstly, we have to use a page with form
inside. Otherwise we won't be able to add a ScriptManager
control. One more thing: the ScriptManager
control should be the first control in the form. Further is easier:
Page page = new Page();
Button button = new System.Web.UI.WebControls.Button
{
ID = "btnSumbit",
Text = "TextButton",
UseSubmitBehavior = true
};
HtmlForm form = new HtmlForm
{
ID="theForm"
};
ScriptManager scriptManager = new ScriptManager
{
ID = "ajaxScriptManager"
};
form.Controls.Add(scriptManager);
form.Controls.Add(button);
page.Controls.Add(form);
using (StringWriter output = new StringWriter())
{
HttpContext.Current.Server.Execute(page, output, false);
context.Response.ContentType = "text/plain";
context.Response.Write(output.ToString());
}
This works. The output is quite large so I decided not to include it into my answer :)
Actually, there is a workaround. Yep, we may render a control in handler.
Firstly, we need a formless page. Because without it we get:
Control 'btnSumbit' of type 'Button' must be placed inside a form tag with runat=server.
public class FormlessPage : Page
{
public override void VerifyRenderingInServerForm(Control control)
{
}
}
Secondly, nobody can prevent us from creating an instance of our FormlessPage
page. And now let's add a control there (I decided to add a Button
control as an example, but you could use any).
FormlessPage page = new FormlessPage();
Button button = new System.Web.UI.WebControls.Button
{
ID = "btnSumbit",
Text = "TextButton",
UseSubmitBehavior = true
};
page.Controls.Add(button);
Thirdly, let's capture the output. For this we use HttpServerUtility.Execute
method:
Executes the handler for the specified virtual path in the context of the current request. A
System.IO.TextWriter
captures output from the executed handler and a Boolean parameter specifies whether to clear theSystem.Web.HttpRequest.QueryString
andSystem.Web.HttpRequest.Form
collections.
Here is the code:
using (StringWriter output = new StringWriter())
{
HttpContext.Current.Server.Execute(page, output, false);
context.Response.ContentType = "text/plain";
context.Response.Write(output.ToString());
}
The result will be:
<input type="submit" name="btnSumbit" value="TextButton" id="btnSumbit" />
In addition I can recommend ScottGu's article Tip/Trick: Cool UI Templating Technique to use with ASP.NET AJAX for non-UpdatePanel scenarios. Hope, you could find a lot of useful there.
Another option is to host the ASP.NET HTTP pipeline in your process, render the page to a stream and read the HTML you need to send from the HttpListenerContext.Response.OutputStream stream after the page has been processed.
This article has details: http://msdn.microsoft.com/en-us/magazine/cc163879.aspx
精彩评论