views:

292

answers:

3

As title, basically I have a user control placed inside a page and then the page is placed inside the master page. I want to extract a block of javascript and put it back to the page head. When I try to wrap the code inside any block control (e.g. a div runat server) and access divID.InnerText then ASP.NET bust off with

Cannot get inner content of startup_script because the contents are not literal.

I dont want to extract JS inside cs file, thats awfully ugly approach (all sort of escapes and people wont even notice you have JS written unless they drill your CS file), what can I do?

A: 
<%@ Page Language="C#"%>
<script runat=server>
    protected override void OnLoad(EventArgs e)
    {
        string scriptText = someID.InnerHtml;
        //if you really want it in the header...
        //Page.Header.Controls.Add( new LiteralControl(String.Format( "<scr" + "ipt language=\"javascript\">{0}</scri" + "pt>\\n", scriptText )));

        //doesnt add to header and requires form runat=server
        Page.ClientScript.RegisterStartupScript(this.GetType(), "SomeScript", scriptText, true);

        base.OnLoad(e);
    }
</script>
<head runat=server></head>
<form runat=server>
<div id="someID" runat=server>alert('hi');</div>
</form>
Chad Grant
I think it would blow when you try to get InnerHtml, thats the same case as what I did- you tried?
goodwill
it works when i tested it
Chad Grant
I mean, the Page.Header.Controls.Add part, the part you commented seems wont work IIRC.
goodwill
it requires the <head runat="server">, but that is production code, so it definitely works
Chad Grant
+1  A: 

You could store the javascript in a separate file, and then add it to the page using Page.RegisterClientScriptBlock()

Add the javascript you want to a .js file and add the .js file to your project. Alter the properties of the .js file so that it is an Embedded Resource.

Then use code like this somewhere in your UserControl (maybe the Page_Load) to pull the code from the file and drop it into the page:

string javaScript = "";
// the javascript is in a separate file which is an 'embedded resource' of the dll
using (StreamReader reader = 
    new StreamReader((typeof(ThisClass).Assembly.GetManifestResourceStream(typeof(ThisClass), "NameOfJavaScriptFile.js"))))
{
    javaScript = String.Format("<script language='javascript' type='text/javascript' >\r\n{0}\r\n</script>", reader.ReadToEnd());
}
Page.RegisterClientScriptBlock("MyScriptBlock", javaScript);

Note that RegisterClientScriptBlock() will put the script near the top of the page, but apparently not in the page header.

(edited bit about header after comment)

codeulike
This wont be put on header AFAIK. The page client script block just throw stuff into the page at the time you call- thats something I hate a lot in ASP.NET. Without exception all JS should stay inside head, thats especially true for me because I am using jQuery to do method hook.
goodwill
ah your right, RegisterClientScriptBlock() is supposed to put the scripts near the start of the page, but it doesn't actually put them in the header. i have edited my answer accordingly
codeulike
A: 

Okay, I've probably done this in a horrible, horrible way, but I wanted to add a script to the head element in a recent project from a user control. This script didn't require any data from my server, but I only wanted it on specific pages, so I put the script in a .js-file, and added it to the head like this:

HtmlGenericControl script = new HtmlGenericControl("script"); // Creates a new script-element
script.Attributes.Add("type","text/javascript");
script.Attributes.Add("src","src/to/js-file.js");
Page.Master.FindControl("head").Controls.Add(script); // Finds the element with ID "head" on the pages master page.

Not entirely sure if the code works as I think it does as the code I wrote for the project is on another machine, but you get the idea, right?

Edit: After googling your error message for a bit, I think this might be a solution to your problem:

using System.IO;

StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
yourDivID.RenderControl(h);
String str = sw.GetStringBuilder().ToString();

If you combine the two examples, you should be able to get the result you want. I haven't tested this, but it works in my head.

Jesper Karsrud
The problem is the script I intend to put on header have some dynamic code needs to be generated runtime on server (e.g. Fill in control id) so including a file is not an option.
goodwill
I see. I've added another snippet that might help you.
Jesper Karsrud