ASP.NET MVC 4 beschert uns ein u.a. ein tolles neues Feature: Bundling&Minification. Darüber habe ich an derer Stelle bereits berichtet. Hier geht es nun um die Vermeidung eines ganz bestimmten Stolpersteines beim unbedachten Einsatz.
Problem
Mir ist da gerade was unangenehmes passiert. Ich setze jQuery Datatables ein, um Daten-Matrizen auf meiner ASP.NET-4-Seite mit AJAX usw. darzustellen. Das klappt ganz gut. Was nicht so schön war, war plötzlich folgender Fehler in der Firebug-Konsole:

Der ausgeblendete Text ist dabei mein Root-Folder. Mit anderen Worten: Meine Seite sucht die beiden Bilder im Ordner „images“ direkt unterhalb meines Root-Folders. Dort liegen die Bildchen aber nicht. Hier meine Struktur im Visual Studio:

Ich habe mal hervorgehoben, was das Problem ist. In meinem Projekt befinden sich die Bilder im Order „Content/DataTables-1.9.4/media/images“ und nicht in „/images“. Logisch, dass er es nicht findet! Welcher Code teilt ihm aber diesen Schrott mit? Noch verwunderlicher: Warum funktioniert es im PageInspector wunderbar? Die Recherche beginnt.
CSS?
Mein erster Verdächtiger ist „jQuery.dataTables.css“. Schließlich wird in dieser Datei ja der Style festgelegt. Hier der interessierende Auszug:
/* * Sorting */ .sorting { background: url('../images/sort_both.png') no-repeat center right; } .sorting_asc { background: url('../images/sort_asc.png') no-repeat center right; } .sorting_desc { background: url('../images/sort_desc.png') no-repeat center right; } .sorting_asc_disabled { background: url('../images/sort_asc_disabled.png') no-repeat center right; } .sorting_desc_disabled { background: url('../images/sort_desc_disabled.png') no-repeat center right; } table.dataTable thead th:active, table.dataTable thead td:active { outline: none; }
Hmmm. Eigentlich alles sauber. Ein relativer Pfad, der zunächst zurück auf „Content/DataTables-1.9.4/media“ und dann rein in „images“ weist. Sollte laufen! Tut es aber nicht.
Bundling
Nach langem Grübeln und Probieren sehe ich mir schließlich mal die Einbindung des CSS in die _Layout an und sehe folgendes:
@Styles.Render("~/Content/jqtable")
Das funktioniert, weil ich in der BundleConfig.cs folgendes definiert habe:
bundles.Add(new StyleBundle("~/Content/jqtable").Include( "~/Content/DataTables-1.9.4/media/css/jquery.dataTables.css"));
Pfade
Und genau in Listing 3 versteckt sich auch das Problem. Der Pfad, dem man dem StyleBundle-Konstruktor übergibt gilt nämlich zur Ausführungszeit als Ankerpfad für das Stylesheet. Was ich da also genau tue ist, das css aus seinem Ordner zu „zerren“ und unter dem Namen „jqtable“ im css-Ordner unterhalb des Root einzubinden. Jetzt macht es natürlich Sinn, dass er dann bei „../images“ im Root-Image-Ordner landet.
Lösung
Die Änderung sind eigentlich trivial:
bundles.Add(new StyleBundle("~/Content/DataTables-1.9.4/media/css/jqtable").Include( "~/Content/DataTables-1.9.4/media/css/jquery.dataTables.css"));
und
@Styles.Render("~/Content/DataTables-1.9.4/media/css/jqtable")
Das wars auch schon! Nun wird das Bundle „jqtable“ an der richtigen Ordner-Struktur eingebunden und damit stimmen auch die darin enthaltenen relativen Pfade wieder.