Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / All-Topics

Configuring Your Assets for FubuMVC

5.00/5 (1 vote)
7 Feb 2017CPOL3 min read 8.6K  
How to configure your assets for FubuMVC

When you have a complicated View, things can easily get messy. A View may have several Partials, each Partial being reused in several Views. Each Partial might require certain library scripts, which in turn might depend on other scripts.

(At this point, I stopped and thought, maybe I should really add images to my posts. Ayende does it, although he has clearly no time for finding an appropriate image. All the cool guys do it. Perhaps I should do it, too.)

<insert a messy picture here>

(By the way, if you know a place where I could quickly steal images for my posts, please tell me in the comments. I heard that it makes them more entertaining and gives a personal touch.)

Turned out FubuMVC provides a nice solution to this problem. You can have an arbitrary number of "config" files (the extension is misleading, they're plain text files) in arbitrary places, named either *.script.config, or *.asset.config. Each file describes relationships between assets, or just groups them for reference. After that, your View just references a file it needs, and your Master issues a directive to render all required files.

How Do You Write A Config File

If you have scripts dependent on each other, you need an ordered set:

ordered set {set name}
{name1}
{name2}

For example:

ordered set jslib is
lib/jquery-1.7.1.js
lib/jquery-ui.js
lib/bootstrap.js
lib/tree.jquery.js
lib/amplify.js

Unordered set:

{set name} includes {name1}, {name2},..

Individual dependencies:

{asset name} requires {name1}, {name2}

For example:

demo.js requires jslib

Ordering individual files:

{asset name} preceeds {another name}

Applying a custom policy (should be a type implementing either IAssetPolicy or ICombinationPolicy):

apply policy {policy type}

Combining assets:

combine {name1}, {name2},.. as {set name}

Alias:

{alias} is {asset name}
e.g., jquery is lib/jquery.min.js

Extending (not sure what it means -- please enlighten me!):

{asset name} extends {another name}

In addition, you can have empty lines for readability, and lines starting with '#' for comments.

How Works Them Config Files?

Suppose you have the pieces provided above in one of your config files. Whenever you need the demo.js script on your page, you just put:

jscipt
<Script src="demo.js" />

somewhere close to the top of your View (assuming you use a Spark ViewEngine with the default bindings; it would work for other Views, of course, but with a slightly different syntax). This directive doesn't output anything, but it tells the Asset Pipeline that you'll need that script at some time. Later, presumably in your Master, you have the following:

jsript
<Scripts />

This should render all the required scripts for the page. In particular, although we have never mentioned we need jQuery, it's going to be referenced, since demo.js needs it. All scripts will be rendered in the correct order. In addition, there won't be any duplicates.

Another good thing is that the config files can be easily reused across different projects. After all, the library dependencies is what doesn't depend on a particular project.

This Can't Be So Good. Now Tell Me the Bad News!

The bad news is that the current implementation enforces rather strict rules for where your assets should be. Namely, everything should be placed in the Content folder, with the hardcoded subfolder names for styles, scripts, and images. This doesn't work good with styles requiring images in a subfolder, and also can cause some friction, e.g. when updating jQuery via NuGet. While having such a rigid structure is a bit unusual for this otherwise very flexible framework, the benefits, in my opinion, outweigh the disadvantages.

For a real-world sample of what I'm talking about, take a look at https://github.com/uluhonolulu/fubumvc/blob/master/src/FubuMVC.Diagnostics/diagnostics.script.config

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)