views:

260

answers:

4

I have a bunch of javascript functions which depend on some server-side constants (such as strings from my resources file). While I was developing them I kept the javascript code in the view header, so I could simply used server-side tags inside my javascript code, but now I'd like to move the javascript functions to a separate file.

I can't use a regular js file since that would not be interpreted by the server, making the server tags embedded there useless. I don't want to define variables in the page either since that seems way to awkward and error-prone.

What I've done instead is to create a new aspx file, put the javascript functions there and include that aspx file instead of a regular js file in my master template. It seems a bit unorthodox, but it seems to work fine.

Is there any downside to my approach that I have not taken into account? Or any better (less obscure) method?

Edit Bonus question: Should I use a DOCTYPE inside the included scripts file? After all, the scripts file is included by a script tag already. I tried to mimic regular js files, so I did not specify any DOCTYPE.

+3  A: 

The file extension, be it js, aspx, ashx, bla, foo, whatever isn't all that important. If you have server side generated javascript that isn't specific to a page, then creating an ASPX page to render the javascript should be okay.

We'll often use HTTP handlers to generate dynamic javvascript in our systems. We also make sure to set the response headers to text/javascript to let the client browser know that we are sending back javascript.

James Conigliaro
Thanks for your answer. Is the doctype really necessary (see my edit above)? If so, what's the exact syntax for javascript files? My google research wasn't very successful.
Adrian Grigore
The doc type really isn't necessary from a browser perspective. We often use caching servers, such as akamai and set up rules to cache certain content types, such as stylesheets and javvascripts for longer, using the doc type header allows us to do so without needing to rely on file names/extensions.
James Conigliaro
+1  A: 

We use the ScriptDataBlock control from JsonFx to emit variables into the page itself. It acts like a dictionary where the key is the variable name (e.g. "MyNamespace.myVar") and the value is a normal C# value (including whole objects). The control emits appropriate namespace generation and type conversion to native JavaScript types. So in that sense it ends up not being "awkward" or "error prone":

myDataBlock["MyApp.myVar"] = myObject;

If you are doing an external file, then a generic .ashx handler is probably your best bet. It will be lighter than a whole aspx page and gives you pretty raw control over the output. Things you will want to be sure to do are to set the "Content-Type" response header to "text/javascript" (technically incorrect but most common MIME type) and for Internet Explorer which tends to not respect the Content-Type header, also set the "Content-Disposition" header to "inline;MyScriptName.js" so it knows the extension of the content.

Also, if these really are "constants" rather than runtime calculated data, you will want to set the "Expires" header to some future date to encourage the browser to cache the result. That will further reduce your server requests.

Edit: no DocType if you are creating JavaScript. DocType is only for markup.

McKAMEY
Thanks for your answer, but your edit confuses me. I decided to use an asxh file as your suggested and I only put javascript code in there. Should I use a doctype?Also, what's the proper syntax for a javascript doctype? I tried to google it, but could not find any info on this.
Adrian Grigore
Sorry for confusion. There is no DocType for JavaScript, as DocTypes are an SQML declaration that describes the DTDs for validating markup. Your JavaScript response should only include script, not markup (including script tags). This way you can reference your handler as an external script and the browser will download it as if it is a static file.
McKAMEY
Content-Type is the header that specifies the MIME type (e.g. "text/javascript) whereas DocType is a tag at the top of HTML pages. Perhaps that's where the confusion is happening. For a JavaScript file, Content-Type is good to have, but a DocType doesn't apply.
McKAMEY
Finally got it... Thanks :-)
Adrian Grigore
Sorry, for being such a pain, but how exactly would an ashx file help in my scenario? I have control over the content-type header, but how can I output the javascript code with server-side tags parsed and replaced? Loading the script from file and writing it via context.Response.Write inside ProcessRequest does not replace the tags.
Adrian Grigore
Interesting, so you are using markup for the replacement? An .ashx won't have a designer surface for building up the scripts. When I do these sorts of things I use formattings strings and do the replacement via `{0}`. Either way You have to be careful to properly encode your strings, etc. when emitting things like `"<%= this.fooString %>"`. I also use the EcmaScriptWriter in JsonFx (an extension of the JSON Serializer) to properly encode strings, Dates, objects, arrays, etc. into JavaScript literals. It's safer and you never have to worry about extra quote characters messing things up.
McKAMEY
If you really wanted to use markup replacement, you could get into T4 templates, as this is what they were intended to do. It all depends when your "constants" would be changing. Build time or runtime? Devid Ebbo has been writing a lot about them lately: http://blogs.msdn.com/davidebb/archive/2009/07/17/two-ways-to-use-t4-templates-support-code-vs-one-time-generation.aspx
McKAMEY
+1  A: 

You are using the MVC framework (your question is tagged as such) right? If so, you can create an action that returns a JavaScriptResult that will be executed on page when it loads:

public class JSController : Controller {
    public ActionResult Headers() {
        // create your variables here
        return JavaScript("alert('hi');");
    }
}

And then you can add it to your aspx/master page:

<script src="/JS/Headers" type="text/javascript"></script>
swilliams
You are right about the plattform I am using. I assume you mean loading the script from a js file and then returning it as Javascript Result (embedding the script as a string within the controller code would be very ugly with 10+ javascript functions...). Unfortunately this doesn't work in my scenario unless I build the script string by string and insert the server-side constants manually. The problem is that the Javascript result is not interpreted by the server, but just passed through to the browser with an appropriate response header.
Adrian Grigore
+1  A: 

Using a view, with MVC's templating capabilities is a great way to accomplish this. It is easy to maintain, well understood and gets the job done fast. The only real trick is to get it to serve the correct content-type. Doing something like this:

    public ActionResult ConfigurationSettings()
    {
        Response.ContentType = "text/javascript";
        return View(Configuration);
    }

Actually gets you text/html content type. The trick is to make sure you get the last word, add this to your controller:

    protected override void Execute(System.Web.Routing.RequestContext requestContext)
    {
        base.Execute(requestContext);
        requestContext.HttpContext.Response.ContentType = "text/javascript";
    }

And you will get the correct content type; ViewResult seems to force it to go text/html.

Wyatt Barnett
Just what I was looking for - Thanks a lot!
Adrian Grigore