0

I tried asking this question a bit differently before, but it wasn't understood, so I'll try another way:

I have an MVC 3 application where I have views in the Views directory as usual. However, for various reasons I need the images for each view to be in the same folder as the view itself, i.e. in my case e.g. Views/Manuals/en-US/name

Here's the route I use:

routes.MapRoute(
                "Parameter",
                "{controller}/{action}/{lang}/{prod}",
                new { controller = "Manuals", action = "Product", lang = "en-US", prod = "name" }
        );

Now, as mentioned, I need the images for this view to be in the same folder, so that the image path can simply be "ATEXSymbol.svg".

When I just have this route, and use a simple relative path like this for the image, what I get is an error like this:

The view 'da-DK/ATEXSymbol.svg' or its master was not found or no view engine supports the searched locations. The following locations were searched: ~/Views/Manuals/da-DK/ATEXSymbol.svg.aspx ~/Views/Manuals/da-DK/ATEXSymbol.svg.ascx ~/Views/Shared/da-DK/ATEXSymbol.svg.aspx ~/Views/Shared/da-DK/ATEXSymbol.svg.ascx ~/Views/Manuals/da-DK/ATEXSymbol.svg.cshtml ~/Views/Manuals/da-DK/ATEXSymbol.svg.vbhtml ~/Views/Shared/da-DK/ATEXSymbol.svg.cshtml ~/Views/Shared/da-DK/ATEXSymbol.svg.vbhtml

So basically, it's looking for the image in the correct language folder, but without the product name folder part, and with one of a number of view extensions appended. I know MVC doesn't really expect this relative path in the same folder, but I pretty much don't have any choice. I'm required to put images in the same folder for purposes out of my hands.

So how can I achieve this?

EDIT:

Actually, I was mistaken a bit above, saying that the product name part of the path was missing, of course it isn't. That part of the path is the name of the view itself. So basically the path I get by a simple relative path (just the name of the image file) in the src attribute creates the correct path for the image. The only problem is that the view file extension is added...

Anyone know how to solve this?

EDIT 2:

BTW, I could have used Url.Content, but for some reason that doesn't work either. If I use this:

<embed  type="image/svg+xml" src="@Url.Content("~/Content/images/da-DK/3153/CheckRotation.svg")"></embed>

...it works...but if I use this (same thing but with the image in the Views folder)...

<embed  type="image/svg+xml" src="@Url.Content("~/Views/Manuals/da-DK/CheckRotation.svg")"></embed>

...it doesn't work. If I inspect the path in the latter example in the web inspector, it looks like the correct path (localhost:49864/Views/Manuals/da-DK/CheckRotation.svg) but with the message that it cannot be found.

EDIT 3:

The answer by Thinking Sites gave me a solution, I just had to modify it a bit, since I needed the route suggested for the views themselves. So I added this route:

routes.MapRoute(
                "Image",
                "{controller}/{action}/{lang}/{prod}",
                new { controller = "Manuals", action = "Image", lang = "en-US", prod = "name" }
        );

I made a slight adjustment in the path (as suggested), since the prod now actually carries the entire filename, including extension:

public ActionResult Image(string lang, string prod)
        {
            var root = Server.MapPath("~/Views/Manuals/");
            var filepath = Path.Combine(root, lang, prod); // whatever creates your path here.
            return File(filepath, "image/svg+xml");
        }

And then in the view I can have paths like this:

<embed  type="image/svg+xml" src="@Url.Content("/Manuals/Image/da-DK/CheckRotation.svg")"></embed>
Anders
  • 12,556
  • 24
  • 104
  • 151
  • The route looks fine to me. I think the problem is in your action. Are you returning a FileResult instead of a ViewResult? – Thinking Sites May 04 '12 at 14:37
  • No, actually this is only the route for the view, and I'm returning an ActionResult. I don't actually know what to do with the route or the action for the SVG images. The routing tries to use this controller for the SVG images as well, but as described above it doesn't work. – Anders May 04 '12 at 14:47
  • The route looks fine. The ActionResult is the base class for FileResult and ViewResult. The error you're getting is because you're looking for a view in your method, not a file. Are you needing to dynamically load the SVG files? Regardless, they should not be in the views folder. If you put them in the content folder instead, you can put just make a url to them directly without having to route. If they are dynamic, then you're looking for a FileResult to load the SVG and send the bytes across. Is there something dynamic in the SVG files themselves? – Thinking Sites May 04 '12 at 15:26
  • Right, no the SVG files are basically just images for views, so they should just display. I actually know how to do it if I place it in the Content folder. However, the client demands (whether it is correct or not) that it should be in the Views folder. This is because content will be dumped in en masse, and they don't want to have to separate stuff like that. It's an unusual context, I know, but that's the situation. So I need to make image links work as relative links in the same View folder... – Anders May 04 '12 at 15:57
  • And you have an action that loads them up, yes? – Thinking Sites May 04 '12 at 16:16
  • I actually don't have an action for the image loading so far, only for views. The decision that images needed to be placed in the same folder as the views was taken recently, so there is no solution for this in place yet because I don't know how to solve it with relative image paths... – Anders May 04 '12 at 20:36
  • I had made a small mistake in my question, edited now. Does that help? – Anders May 04 '12 at 20:57

2 Answers2

1

Using this route:

routes.MapRoute(
                "Parameter",
                "{controller}/{action}/{lang}/{prod}",
                new { controller = "Manuals", action = "Product", lang = "en-US", prod = "name" }
        );

Create this action in your controller ManualsController

public ActionResult Product(string lang,string prod){
   var root = Server.MapPath("~/views/manuals/");
   var filepath = Path.Combine(root,lang,prod,".svg"); // whatever creates your path here.
   return File(filepath ,"your mime type");
}

No need for a custom view engine. The FileResult is designed for just this occasion.

Thinking Sites
  • 3,494
  • 17
  • 30
0

Maybe the answer to your question is in your error:

The view 'da-DK/ATEXSymbol.svg' or its master was not found or no view engine supports the searched locations.

Have you thought about plugging in a custom view engine?

I have never created one myself & can't offer guidance, so this is an incomplete answer (I can delete later depending on comments). It's an interesting problem though, and so far as I can tell a unique one. I wonder who would dictate that items be "dumped in en masse" for a framework that doesn't work that way by convention. Pretty straightforward if you were working with web forms though.

danludwig
  • 46,965
  • 25
  • 159
  • 237
  • I know, it's unconventional, but different requirements for different reasons make it so... I have thought about custom view engine as well as custom route handler, but unfortunately I haven't been able to get it to work so far either. – Anders May 04 '12 at 20:42
  • I had made a small mistake in my question, edited now. Does that help? – Anders May 04 '12 at 21:00
  • The view file extension must come from the view engine. I think you're going to have to go down the custom view engine road. – danludwig May 04 '12 at 22:01
  • It's not necassary. All you need is the file path and pass them into a FileResult. – Thinking Sites May 04 '12 at 22:27