简体   繁体   中英

Add ASP.NET server script to mostly-static .JS / .CSS files without losing IntelliSense?

Using VS2008 and ASP.NET 3.5 (or VS 2010 / .NET 4.0?), how can I include a bit of dynamic ASP.NET server-side code in mostly-static JavaScript and CSS files?

I want to do this to avoid cloning entire JS or CSS files to vary just a small part of them multi-tenant sites. Later, I want to extend the solution to handle localization inside javascript/CSS, dynamic debugging/tracing support, and other cool things you can get by injecting stuff dynamically into JavaScript and CSS.

The hard part is that I don't want to lose all the cool things you get with static files, for example:

  • JS/CSS code coloring and intellisense
  • CSS-class "go to definition" support in the IDE
  • automatic HTTP caching headers based on date of underlying file
  • automatic compression by IIS

The server-side goodness of static files (eg headers/compression) can be faked via an HttpHandler, but retaining IDE goodness (intellisense/coloring/etc) has me stumped.

An ideal solution would meet the following requirements:

  1. VS IDE provides JS/CSS intellisense and code coloring. Giving up server-code intellisense is OK since server code is usually simple in these files.
  2. "go to defintion" still works for CSS classes (just like in static CSS files)
  3. send HTTP caching headers, varying by modified date of the underlying file.
  4. support HTTP compression like other static files
  5. support <%= %> and <script runat=server> code blocks
  6. URL paths (at least the ones that HTTP clients see) end with .JS or .CSS (not .ASPX). Optionally, I can use querystring or PathInfo to parameterize (eg choosing a locale), although in most cases I'll use vdirs for this. Caching should vary for different querystrings.

So far the best (hacky) solution I've come up with is this:

  • Switch the underlying CSS or JS files to be .ASPX files (eg foo.css.aspx or foo.js.aspx). Embed the underlying static content in a STYLE element (for CSS) or a SCRIPT element (for JS). This enables JS/CSS intellisense as well as allowing inline or runat=server code blocks.
  • Write an HttpHandler which:
    • looks at the URL and adds .aspx to know the right underlying ASPX to call
    • uses System.Net.HttpWebRequest to call that URL
    • strips out the containing STYLE or SCRIPT tags, leaving only the CSS or JS
    • adds the appropriate headers (caching, content type, etc.)
    • compresses the response if the client suports compression
  • Map *.CSS and *.JS to my handler.
  • (if IIS6) Ensure .JS and .CSS file extensions are mapped to ASP.NET

I'm already using a modified version of Darick_c's HttpCompression Module which handles almost all of above for me, so modifying it to support the solution above won't be too hard.

But my solution is hacky. I was wondering if anyone has a more lightweight approach for this problem which doesn't lose Visual Studio's static-file goodness.

I know I can also hack up a client-side-only solution where I split all JS and CSS into "vary" and "won't vary" files, but there's a performance and maintenance overhead to this kind of solution that I'd like to avoid. I really want a server-side solution here so I can maintain one file on the server, not N+1 files.

I've not tried VS10/.NET 4.0 yet, but I'm open to a Dev10/.net4 solution if that's the best way to make this scenario work.

Thanks!

I have handled a similar problem by having a master page output a dynamic generated JSON object in the footer of each page.

I needed to have my js popup login dialog box support localization. So using JSON.NET for serialization, I created a public key/value collection property of the master page that pages could access in order place key/values into such as phrase key/localized phrase pairs. The master page then renders a dynamic JSON object that holds these values so that static js files could reference these dynamic values.

For the js login box I have the masterpage set the localized values. This made sense because the masterpage also includes the login.js file.

I do commend you on your concern over the number of http requests being made from the client and the payload being returned. Too many people I know and work with overlook those easy optimizations. However, any time I run into the same issue you're having (which is actually quite often), I have found I've usually either taken a wrong turn somewhere or am trying to solve the problem the wrong way.

As far as your JS question goes, I think Frank Schwieterman in the comments above is correct. I'd be looking at ways to expose the dynamic parts of your JS through setters. A really basic example would be if you have want to display a customized welcome message to users on login. In your JS file, you can have a setMessage(message) method exposed. That method would then be called by the page including the script. As a result, you'd have something like:

<body onLoad="setMessage('Welcome' + <%= user.FirstName %>);">

This can obviously be expanded by passing objects or methods into the static JS file to allow you the functionality you desire.

In response to the CSS question, I think you can gain a lot from the approach Shawn Steward from the comments makes a good point. You can define certain static parts of your CSS in the base file and then redefine the parts you want to change in other files. As a result, you can then dictate the look of your website by which files you're including. Also, since you don't want to take the hit for extra http requests (keep in mind, if you set those files to be cached for a week, month, etc. it's a one time request), you can do something like combining the CSS files into a single file at compilation or runtime.

Something like the following links may be helpful in pointing you in the right direction:

http://geekswithblogs.net/rashid/archive/2007/07/25/Combine-Multiple-JavaScript-and-CSS-Files-and-Remove-Overheads.aspx

http://www.asp.net/learn/3.5-SP1/video-296.aspx?wwwaspnetrdirset=1

http://dimebrain.com/2008/04/resourceful-asp.html

By utilizing the combining at run or compile time you can gain the best of both world by allowing you to logically separate CSS and JS files, yet also gaining the reduction of payload and requests that comes with compressing and combining files.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM