tags:

views:

281

answers:

6

Using C# for ASP.NET and MOSS development, we often have to embed JavaScript into our C# code. To accomplish this, there seems to be two prevalent schools of thought:

string blah = "asdf";
StringBuilder someJavaScript = new StringBuilder();
someJavaScript.Append("<script language='JavaScript' >");
someJavaScript.Append("function foo()\n");
someJavaScript.Append("{\n");
someJavaScript.Append("  var bar = '{0}';\n", blah);
someJavaScript.Append("}\n");
someJavaScript.Append("</script>");

The other school of thought is something like this:

string blah = "asdf";
string someJavaScript = @"
    <script language='JavaScript' >
    function foo()
    {
      var bar = '" + blah + @"';
    }
    </script>";

Is there a better way than either of these two methods? I like the second personally, as you can see the entire section of JavaScript (or other language block, whether SQL or what have you), and it also aids in copying the code between another editor for that specific language.

Edit:
I should mention that the end goal is having formatted JavaScript in the final web page.

I also changed the example to show interaction with the generated code.

+2  A: 

How about adding the JavaScript as a resource section to the file, so that it can be loaded as an (embedded) script from the resource section of the executable?

none
yeah.. this just makes it hard to work with. they're already starting from a disadvantage having to work with MOSS, it's best to just do something like this in most cases.
Matt Hinze
Not if you organize your code carefully. My experience is that there is usually just a few IDs and such that you have to pull from the server side code. These can be inserted in initializers embedded much as you do above. If you want formatting and readability, use JS files.
Ishmael
@Ishmael, can you provide an example of using initializers with your resources?
Nathan DeWitt
none, if you load the JS as an embedded script in the resource section, you still have to recompile to change it, right? What's the benefit over having it right in with your code?
Nathan DeWitt
Yes, normally you will have to recompile your application if you change anything inside the executable, even though you could of course just use a resource editor (e.g. PE explorer) instead. The major benefit would be to have distinct files represented as sections inside the executable, so there's a form of separation between your c# code and the javascript, making it easier to maintain/update, while keeping everything still self-contained (otherwise you could also just load a standalone *.js file). Also, you could of course encrypt the embedded js file easily if need should arise.
none
+1  A: 

The string literal for one reason: readability.

(performance is a non-issue, this is MOSS we're talking about...)

Matt Hinze
This applies to a lot of languages, ie - embedding SQL in VB for example.
Nathan DeWitt
+6  A: 

The second is obviously way, way, clearer. There couldn't really be any reason at all for doing the first.

I would, however, extend it to this:

string someJavaScript = string.Format(@"
    <script language='JavaScript' >
      function foo()
      {
          var bar = '{0}';
      }
    </script>", blah);

If you have several things to stick inside the string, the string.Format method will become rather more readable than inline concatenation.

mquander
that's a very good suggestion, although it could get unwieldy quickly with a bunch of substitutes.
Nathan DeWitt
A: 

For portability reasons I would choose StringBuilder over the other. Languages like VB do not have the ability to line-break in the middle of a string. So if theres a chance that this code will someday have to be ported to another language I'd go with StringBuilder.

Boo
what's the likelihood of that? yagni.
Matt Hinze
How should I know. If it happens then the liklihood is 100%. If it doesnt then its 0%. Point is that whenther it should or should not happen - it often DOES happen.
Boo
well, it won't happen on our projects, but you make a good point, Boo.
Nathan DeWitt
If it needs to be ported to another language, they can replace the multi-line literal with a StringBuilder version. I wouldn't agree that it's reasonable to make the code less maintainable just you may port it later (at which point, you'd be changing many other things anyways).
RHSeeger
To be safe, I only use the subset of C# that is also legal C++. What if I need to port it to C++ someday?
mquander
This makes little sense. To port it to VB you'd have to edit every line anyway because VB syntax for calling a method is different. On the day this happens, just move the JS into an external file, which will be easy if you use a single literal (and this will be item number 1,000,000 on your list of problems, by the way).
Daniel Earwicker
+5  A: 

The second way, although using an external file is much better and allows modifications to be made to the application without recompiling it all.

You also need a nice, readable way to insert variables. The simplest approach is to use string.Format, but then each variable is {0} or {1} and so this can be unreadable.

How about:

public static string Insert(object dictionary, string into)
{
    foreach (PropertyInfo property in dictionary.GetType().GetProperties())
        into = into.Replace("<%" + property.Name + "%>", 
                            property.GetValue(dictionary, null).ToString());

    return into;
}

Then you can do this:

string js = Insert(new { divList, url }, 
                   @"jQuery(document).ready(function(){
                        jQuery('#<%divList%>').jqGrid({
                            url:'<%url%>',
                            datatype: 'json',
                            mtype: 'GET', ... etc...");

Or if the script is in an external file:

string js = Insert(new { divList, url }, File.ReadAllText("someFile.js"));

You can pass any object and its properties will be directly accessible via an ASP-style escaping syntax.

The implementation given above is not very efficient, obviously, but it's short.

Another possibility is to write an .aspx page that returns JavaScript, and then you can include it in your HTML pages with a <script> reference. You can set the ContentType of the page to be application/x-javascript.

This will let you use normal ASP.NET <%= %> tags to modify it, and will already be a fast, robust solution with external files, compiling automatically on the fly when you make edits to the script.

Daniel Earwicker
Can you give an example to have it in an external file to avoid the recompile? the answer provided by none mentioned putting itin the resource section of the executable, but that would require a recompile to change it.
Nathan DeWitt
I've added a very simple example of that - you'd probably want to use the ASP.NET path mapping functions if you're building that sort of app, to locate the file within your web app.
Daniel Earwicker
Very interesting. I wonder how easily this translates to the MOSS Web Part/Solution paradigm...
Nathan DeWitt
A: 

We wrote a library just for this purpose, that offers a fluent-syntax to embedding JavaScript in C# code. You can read more about it here.

In short, your example would be written as:

var function = JS.Function("foo").Do(
    JS.Var(JS.Id("bar").AssignWith(blah)));
string someJavaScript = "<script>" + function + "</script>";

For one, it will make sure that the contents of the blah variable is properly quoted, if it contains special characters, for example.

Dave Van den Eynde