In ASP.NET, is it possible to get the values of __VIEWSTATE and __EVENTVALIDATION hidden fields into a variable in C# (server side) in, let's say, overriding the Render method?
I have tried:
protected override void Render(HtmlTextWriter writer)
{
StringBuilder stringBuilder = new StringBuilder();
StringWriter stringWriter = new StringWriter(stringBuilder);
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
base.Render(htmlWriter);
string temp = stringBuilder.ToString();
}
This gives me the entire ASP.NET output. We can get the values by using a string function, but I did not find it a very clean solution. Is there a better way to do this?
What I actually want is the values of __VIEWSTATE & __EVENTVALIDATION when the first request is made and not after the postback is done. That is when the output stream if formed when the first request is made.
If you look at the Page class using Reflector, you'll see these hidden fields are created during the render phase (look at the methods RenderViewStateFields and EndFormRenderHiddenFields).
You could probably get at some/all of the data using reflection (e.g. the internal property Page.ClientState).
But I don't think there is a clean solution (though to be honest I don't really understand what you're trying to achieve).
To get the event validation you should use HTML Agility Pack.
var eventValidation = HapHelper.GetAttributeValue(htmlDocPreservation, "__EVENTVALIDATION", "value");
public static string GetAttributeValue(HtmlDocument doc, string inputName, string attrName)
{
string result = string.Empty;
var node = doc.DocumentNode.SelectSingleNode("//input[#name='" + inputName + "']");
if (node != null)
{
result = node.Attributes[attrName].Value;
}
return result;
}
Related
I need retrieve the HTML code for a page that uses the AngularJS to process some information and generate a graph. I could easily retrieve the html code using WebRequest, as the example below, but the content (graphic) generated by AngularJS does not come in the page code.
WebRequest request = WebRequest.Create("http://localhost:36789/minhaapp#/index");
WebResponse response = request.GetResponse();
Stream data = response.GetResponseStream();
string html = String.Empty;
using (StreamReader sr = new StreamReader(data))
{
html = sr.ReadToEnd();
}
Has anyone ever experienced this?
Thank you in advance for your support.
At the end of your Page_Load method, call this getHTMLContent() method:
public string getHTMLContent()
{
StringBuilder sb = new StringBuilder();
StringWriter tw = new StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(tw);
panel.RenderControl(hw);
String html = sb.ToString();
return html;
}
The entire page is contained in an asp:Panel called panel. The way this works is from the RenderControl() method which you can read a little bit more about here. Simply put, it gets all the content within the asp:Panel tags (the whole page) and once used after the Page_Load event has been executed, it will get all the raw HTML for the page.
There's a library called PhantomJS, which renders the js off the site first and then u can get the source after it got rendered. But obviously it will also slow down the process if you are doing a lot of websites
I am able to get the HTML from the code-behind, like this one:
protected override void OnPreRenderComplete(EventArgs e)
{
StringWriter sw = new StringWriter();
base.Render(new HtmlTextWriter(sw));
sbHtml = sw.GetStringBuilder();
Response.Write(sbHtml + "<!-- processed by code-behind -->");
}
But I need to remove the HTML from the Page, any help?
If I understand well you wish to manipulate the sbHtml, and write it out.
sbHtml = sw.GetStringBuilder();
sbHtml.Replace('anything','to anything');
Response.Write(sbHtml);
(or is something else ?)
Did you want a method like this to strip the HTML?
public static string StripHTML(string HTMLText)
{
var reg = new Regex("<[^>]+>", RegexOptions.IgnoreCase);
return reg.Replace(HTMLText, "").Replace(" ", "");
}
You can put an <asp:placeholder> on the page and set the contents to whatever you want. Add/remove/whatever.
I have a server control that has a PlaceHolder that is an InnerProperty. In the class when rendering I need to get the text / HTML content that is supposed to be in the PlaceHolder. Here is a sample of what the front end code looks like:
<tagPrefix:TagName runat="server">
<PlaceHolderName>
Here is some sample text!
</PlaceHolderName>
</tagPrefix:TagName>
This all works fine except I do not know how to retrieve the content. I do not see any render methods exposed by the PlaceHolder class. Here is the code for the server control.
public class TagName : CompositeControl
{
[TemplateContainer(typeof(PlaceHolder))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public PlaceHolder PlaceHolderName { get; set; }
protected override void RenderContents(HtmlTextWriter writer)
{
// i want to retrieve the contents of the place holder here to
// send the output of the custom control.
}
}
Any ideas? Thanks in advance.
I just found the solution. I did not see the render methods because of the context of how I was using the PlaceHolder object. Eg I was trying to use it as a value and assign it to a string like so:
string s = this.PlaceHolderName...
Because it was on the right hand side of the equals Intellisense did not show me the render methods. Here is how you render out a PlaceHolder using and HtmlTextWriter:
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
this.PlaceHolderName.RenderControl(htw);
string s = sw.ToString();
Posting this as a second answer so I can use code formatting. Here is an updated method that uses Generics and also uses the 'using' feature to automatically dispose the text / html writers.
private static string RenderControl<T>(T c) where T : Control, new()
{
// get the text for the control
using (StringWriter sw = new StringWriter())
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
c.RenderControl(htw);
return sw.ToString();
}
}
Since i havn't access to the TemplateControl or page from a WCF service i was wondering if it was possible to render a custom control? If so how would one do it?
private string GetRenderedHtmlFrom(Control control)
{
StringBuilder stringBuilder = new StringBuilder();
StringWriter sw = new System.IO.StringWriter(stringBuilder);
HtmlTextWriter htmlWriter = new HtmlTextWriter(textWriter);
control.RenderControl(htmlWriter );
return stringBuilder.ToString();
}
Thanks
This actually wasn't achievable and i ended up abandoning the idea. The rough solution i implemented was loading an html page, and using string.Format() to manipulate it then returned the results as a string and let the JavaScript 'load the control'.
I am not able to get xml response data from .aspx page of VS 2005. Following is the function which writes xml response on the client end:
protected void GetMailContents(double pdblMessageID)
{
string lstrMailContents = "";
DataSet lobjDs = new DataSet();
StringBuilder stringBuilder = new StringBuilder("<MailContents>");
lobjDs = mobjCProfileAndMail.GetMailContents(pdblMessageID);
if (lobjDs != null)
{
stringBuilder.Append("<Contents><From>");
stringBuilder.Append(lobjDs.Tables[0].Rows[0]["From"].ToString());
stringBuilder.Append("</From><To>");
stringBuilder.Append(lobjDs.Tables[0].Rows[0]["To"].ToString());
stringBuilder.Append("</To><Subject>");
stringBuilder.Append(lobjDs.Tables[0].Rows[0]["Subject"].ToString());
stringBuilder.Append("</Subject><Message>");
stringBuilder.Append(lobjDs.Tables[0].Rows[0]["Message"].ToString());
stringBuilder.Append("</Message></Contents>");
}
stringBuilder.Append("</MailContents>");
lstrMailContents = "<?xml version=\"1.0\" encoding=\"utf-8\"?> \n ";
lstrMailContents += stringBuilder.ToString();
Response.ContentEncoding = Encoding.UTF8;
Response.Write(lstrMailContents);
Response.End();
}
Code on the client end:
$(document).ready(function()
{
var varURL = document.URL;
var varArr = varURL.split('=');
var varMessageID = varArr[1];
$.get("AjaxData.aspx?Mode=MODALDIALOG."+varMessageID, function(data)
{
$(data).find('Contents').each(function()
{
var varFrom = $(this).find('From').text();
var varTo = $(this).find('To').text();
var varSubject = $(this).find('Subject').text();
var varMessage = $(this).find('Message').text();
alert(varFrom);
});
});
});
I have written a alert for the data coming from the callback but getting nothing. If I am parsing any fixed xml then its working fine but in case getting response from the .aspx page got nothing. Is there any one who can help me out for this problem.
Thanks.
First - writing xml through concatenation is really flakey - consider using XmlWriter / XDocument / XmlDocument instead, which will automatically escape any necessary symbols (<, &, etc) rather than result in invalid xml.
Did you clear the response buffer before writing to it? In reality, it would be a lot simpler to do this from a raw handler (ashx) than from within the aspx page life-cycle. Or switch to MVC, which works similarly to the ashx result.
Also - from within the jquery, you should probably speficy the type as xml - see here.
Here's an example of a suitable handler:
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/xml";
XmlDocument doc = new XmlDocument();
XmlElement root = (XmlElement) doc.AppendChild(doc.CreateElement("Contents"));
root.AppendChild(doc.CreateElement("From")).InnerText = "some text";
root.AppendChild(doc.CreateElement("To")).InnerText = "some more text";
root.AppendChild(doc.CreateElement("Subject")).InnerText = "this & that";
root.AppendChild(doc.CreateElement("Message")).InnerText = "a < b > c";
doc.Save(context.Response.Output);
}
First off, no need for aspx here - plain IHttpHandler will do and will also be a more natural solution.
As for the question, make sure you clear the output stream before writing out XML and ensure that HTTP headers (specifically Content-Type) are correct. Use Fiddler to see what's going on under the hood.