T4MVC / R4MVC

R4MVC is a Roslyn code generator for ASP.NET Core MVC apps that creates strongly typed helpers that eliminate the use of literal strings in many places
Apache License 2.0
157 stars 48 forks source link

Virtual paths from links aren't converted to absolute paths #75

Closed artiomchi closed 6 years ago

artiomchi commented 7 years ago

So this is an interesting one.

If you have an image tag with a virtual path:

<img src="~/logo.png" />

the ASP.NET Core Tag Helpers will convert it to a local project path, like so:

<img src="/logo.png" />

The problem is, if the source for the attribute comes from a variable, that conversion doesn't happen. Since our @Links are generated with virtual paths, that causes an issue.

This needs investigation and fixing :)

artiomchi commented 7 years ago

OOoooh boy.. That took a lot of going through the aspnet source code (got to learn a bunch of inner workings though, so.. time well spent!). The tag helpers are assigned to specific tags at compile time, rather than at run time, which means ~ urls won't be processed if they come from a variable (i.e. decided at runtime).

You can see these issues for more details: aspnet/Mvc#5003 and aspnet/Razor#759#220861682

Solution? Well, we have to ensure that link URLs are actually being converted to relative paths. There are a couple ways to do that, and none are quite as elegant as just using the src attribute and putting the link there.

  1. We create a custom tag helper, and users can use something like:
    <img mvc-src="@Links.logo_png" />
  2. To use the generated link urls, we tell users to use Url.Content:
    <img src="@Url.Content(Links.logo_png)" />
  3. Links will generate non relative urls by default (i.e. /logo.png instead of ~/logo.png). But that's not a good solution, even if we make it an optional feature that can be configured

Would love some input on this from the community!

kevinkuszyk commented 7 years ago

I'll put my vote in for option 1.

artiomchi commented 7 years ago

That's probably the easiest solution, and sort of consistent with R4Mvc, even if it looks less... "native".

I'm leaning towards the same option as well, so I'll implement it in the next release. We'll also have a code analysis rule eventually to catch these, and show a hint to the user when they use the src attribute