3

This app has several routes configured in RouteConfig.cs. For instance, I have the two following routes defined:

routes.MapRoute(
  name: "MyPage-Demo",
  url: "pages/page-title/demo",
  defaults: new { controller = "Root", action = "PageDemo" }
);

routes.MapRoute(
  name: "MyPage",
  url: "pages/page-title/{resource}",
  defaults: new { controller = "Root", action = "Page", resource = UrlParameter.Optional }
);

Each page someone visits has a link to a "demo". A page could be accessed by visiting http://localhost/pages/page-title. This works fine.

When a user clicks the "demo" link, they are redirected to a page located at http://localhost/pages/page-title/demo. This works fine.

My problem is the demo page may reference a complex nested structure. The structure consists of JavaScript, css, images, etc. Content used for the purpose of the demo. None of these nested resources can be found. However, I'm not sure how to setup my routing to account for these nested files.

I'm confident I'm going to need to update my controller's PageDemo action. However, I'm not sure

a) how to do so in a way that will allow for differing structures and

b) how to update my route configuration to account for these nested structures.

Is there a way to do this? In reality, I'm going to have multiple pages and multiple demos. For that reason, I want to have something a little more reusable than a hard-coded approach.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
user70192
  • 13,786
  • 51
  • 160
  • 240
  • Are you doing routing for your static contents such as JS, css etc? – Kundan Singh Chouhan Aug 24 '13 at 16:20
  • I hate to say this, but I'm not sure. Essentially, each PageDemo will have its own unique structure of JS/Images/css, etc. The Pagedemo will always be static HTML. For that reason, I would say the content is static, but I'm not sure about the route itself. Am I making sense? – user70192 Aug 24 '13 at 18:05
  • I'm sorry, I don't understand what you're saying. When I visit /pages/page-title/demo/index.html, there is a reference to a JavaScript file. That reference is 'resources/javascript/index.html.js'. However, index.html cannot locate that file. The reference to 'resources/javascript/index.html.js' returns a 404. – user70192 Aug 25 '13 at 12:36
  • 1
    Where are you physically storing the js/css for each demo? – Kevin Stricker Aug 26 '13 at 22:55
  • Can you show the code where you are referencing the content files? – wilsjd Aug 26 '13 at 23:58
  • @mootinator - I am physically storing he js/css for each demo in /Pages/Page-Title/Demo. Within the Demo directory is a directory called "resources/js". – user70192 Aug 27 '13 at 00:26
  • @wilsjd - My code for referencing the content files is just ... ... index.js is never found – user70192 Aug 27 '13 at 00:28
  • Your last few comments show that you are looking for index.js and index.html.js. Are you sure you have the right file name in your path? (Given you have called it two different things here) – Tommy Aug 27 '13 at 14:05

7 Answers7

2

If you just need to serve files physically stored in a path, you should be able to just ignore the route, e.g.:

routes.IgnoreRoute("pages/page-title/demo/resources/{*resource}");

That will bypass MVC trying to route the request to a controller.

Or you could go by file extension:

routes.IgnoreRoute("{file}.js");
routes.IgnoreRoute("{file}.css");

(Code is untested, but it looks like you're trying to do something similar here :) https://stackoverflow.com/a/3112192/486620

Community
  • 1
  • 1
Kevin Stricker
  • 17,178
  • 5
  • 45
  • 71
  • personally, I have never seen a "*" character used in a route before. I'll have to try this approach later today. However, if that does what I think it will, we should have a winner! – user70192 Aug 27 '13 at 11:44
  • Having now done some testing I'm not sure why you're having problems. I have no issues accessing css/js files stored at `%projectroot%/pages/page-title/demo/resources` Are you trying to point to `%projectroot%/Content/pages/page-title-demo/resources` or something? – Kevin Stricker Aug 29 '13 at 16:19
2

IF I understand:

The problem seems to be that your MyPage-Demo route:

routes.MapRoute(
  name: "MyPage-Demo",
  url: "pages/page-title/demo",
  defaults: new { controller = "Root", action = "PageDemo" }
); 

is NOT {resource} specific, while your MyPage route IS.

If you change your route to take a {resource}

routes.MapRoute(
  name: "MyPage-Demo",
  url: "pages/page-title/demo/{resource}",
  defaults: new { controller = "Root", 
        action = "PageDemo", resource = UrlParameter.Optional  });

Then your action method can

  1. return specific Views with proper resource settings
  2. set a Viewbag property with path to your specific resource

If this is inline with your intent, these routes can be consolidated into

routes.MapRoute(
  name: "MyPage-Demo",
  url: "pages/{action}/{resource}",
  defaults: new { controller = "Root", 
        action = "PageDemo", resource = UrlParameter.Optional  });
  1. /pages/PageDemo/{resource} resolves to Controller=pages, action = PageDemo
  2. /pages/demo/{resource} resolves to Controller=pages, action = demo.

This convention allows you flexibility to create more {resource} dependant links

Dave Alperovich
  • 32,320
  • 8
  • 79
  • 101
1

In the Browser, Right Click Demo page => Choose View Page Source.

Here, you have the link for the CSS and Js files in your Demo page. Click on those js/css file links. Check if there are redirecting you to the correct/expected location. Otherwise you could make the Css/Js file URL accordingly Because, as per the demo page each PageDemo will have its own unique structure of JS/Images/css, etc

Imad Alazani
  • 6,688
  • 7
  • 36
  • 58
0

How are you referencing your JS and CSS files ?

If you use the tilde character like : ~/Content/Styles/Site.css you won't have any problem no matter where you are in your virtual path.

Bart Calixto
  • 19,210
  • 11
  • 78
  • 114
0

Also not 100% sure I am directly answering your question, but making the assumption that the resources you are trying to access are nested in a folder structure that mirrors the page structure - and the issue you are having is how to ignore the routes to these without having to know what they might be in advance?

This does a good job of explaining that: https://stackoverflow.com/a/30551/1803682

I would ask:

  1. As @PKKG notes in his answer - do the links in the page source match what you expect?
  2. How is this per-demo content served: e.g. by a service and not a static file?
Community
  • 1
  • 1
Matthew
  • 9,851
  • 4
  • 46
  • 77
0

this answer contains two approaches. the second one may be more suitable for your scenario. the first may be more suitable for a general mvc project

approach one

i suggest creating a organized structure in your content folder to store the scripts and css files, ie

/Content/Demos/Page-Title-1/
/Content/Demos/Page-Title-2/
/Content/Demos/Page-Title-3/

and

/Content/Demos/Common/

and then make a bundle to render the scripts and css files for each page title

ie.

bundles.Add(new StyleBundle("~/Demo/page-title/css").Include(
          "~/Content/Demos/Page-Title-1/csscontent1.css",
          "~/Content/Demos/Page-Title-1/csscontent2.css",
          "~/Content/Demos/Page-Title-1/csscontent3.css",
          "~/Content/Demos/Page-Title-1/csscontent4.css"));

bundles.Add(new StyleBundle("~/Demo/page-title/js").Include(
      "~/Content/Demos/Page-Title-1/jscontent1.css",
      "~/Content/Demos/Page-Title-1/jscontent2.css",
      "~/Content/Demos/Page-Title-1/jscontent3.css",
      "~/Content/Demos/Page-Title-1/jscontent4.css"));

this will allow you to render the scripts on the demo page using a few line approach, ie.

@Styles.Render("~/Demo/page-title/css");
@Scripts.Render("~/Demo/page-title/jss");

@Styles.Render("~/Demo/common/css");
@Scripts.Render("~/Demo/common/css");

you will have to update the files in global .asax as you change the files in your /Content/Demos/Page-Title/ folder. there is the benefit that if you choose, you may bundle and minify the files to save bandwidth and load time for the first page load.


approach two.

(still use the following folder structure

/Content/Demos/Common/

and

/Content/Demos/Page-Title-1/
/Content/Demos/Page-Title-2/
/Content/Demos/Page-Title-3/)

make an html helper to reference all the scripts & contents in a folder

its usage would be @Asset.RenderAssets( '~/folderdirectory')

and the helper would do something like

@helper RenderAssets (stirng directory){

@* scrape the directory for all script files*
var scripts = find all scripts in the directory

@* include the script files *@
for each script
  <script src=" ... .js"></script>


@* scrape the directory for all cssfiles*
var styles = all css in the directory

@* include the css files *@
for each style
<link rel='stylesheet' type="text/css" href=" ... .css">

}

this would be a few line usage in each demo view

@Asset.RenderAssets( '~/Content/Demos/Common')
@Asset.RenderAssets( '~/Content/Demos/Page-Title')

you may or may not need to pair this with an extra few line or two in your global.asax or RouteConfig.cs file (see source 3)

routes.IgnoreRoute("/Content/Demos/{page}/{script}.js");
routes.IgnoreRoute("/Content/Demos/{page}/{style}.css");

relevant sources to create html helpers see http://weblogs.asp.net/scottgu/archive/2011/05/12/asp-net-mvc-3-and-the-helper-syntax-within-razor.aspx

to use bundling and minifcation (the scripts.render approach) see http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

phill haakk says may not need to pair this with an ignore route! https://stackoverflow.com/a/30551/1778606

commentary and edits are encouraged.

Community
  • 1
  • 1
monkeyhouse
  • 2,875
  • 3
  • 27
  • 42
0

All static content (.js, .css, .html, .png) is not seen by MVC (unless modules/runAllManagedModulesForAllRequests is set to true in web.config). Static content extensions are defined in IIS configuration "module mapping", and is using the StaticFileHandler module (and not the .NET module).

So static content must be referenced by its physical path relative to the current path (the path of the current html page).

The best solution is to use absolute link from the root of the website. Like /content/demo1/demo1.html, put all js,css in /content/demo1/, and in demo1.html use path relative to the /content/demo1/ folder (where the .html is). Ie: with demo1.css being in the same folder.

The link to demo1.html would be demo 1

Softlion
  • 12,281
  • 11
  • 58
  • 88