ResolveUrl/ResolveClientUrl equivalents for Asp.Ne

2019-02-11 12:03发布

问题:

So I've started using the <%: Url.Content(~/site/blah) %> syntax as standard for CSS, JScript and Image urls - solves a lot of issues indeed; and it's at least consistent beween WebForms and Razor pages (not all of my devs will be doing Razor, and yet they will still be working on this platform I've produced).

However, for something that I'm doing at the moment I could really do with a way to take a relative Url written in a Razor page and, at run time, resolve it to the correct server side file, before turning it back into an absolute Url for the client. Url.Content doesn't do anything with relative Urls.

So, basically, I want either an equivalent of ResolveUrl or ResolveClientUrl at the Razor level.

I would like this to enable terser (and more tolerant to renaming) resource paths in some of my MVC views, which can be a few folders further down from the root, and whose content folder would be more easily expressed as a relative path - so I could have:

folder\folder\views\shared\layout.cshtml
and
folder\folder\content\site.css

(I've inferred the use of a layout page, also, to mirror the kind of issues that are addressed by ResolveUrl and the re-basing that WebForms does)

Using Url.Content as it is, I would need to specify the full path:

Url.Content("~/folder/folder/content/site.css")

But what I would like is

Url.Content("../../site.css")

And have that work, of course, regardless of how many paths there are in the current request's route.

Of course I can get this to work in WebForms, if I ditch the Url.Content call and just rely on url rebasing.

Is there any equivalent in Razor?

回答1:

You could try using WebPageRenderingBase.Href method like this

@Href("../../site.css")


回答2:

If you are converting ASP.NET application ASP.NET MVC step by step, you can use wrappers:

public abstract class ResolveClientUrlWrapper
{
    public abstract string ResolveClientUrl(string relativeUrl);
}

public class ResolveClientUrlPageWrapper : ResolveClientUrlWrapper
{
    System.Web.UI.Page _page;

    public ResolveClientUrlPageWrapper(System.Web.UI.Page page)
    {
            _page = page;
    }

    public override string ResolveClientUrl(string relativeUrl)
    {
        return _page.ResolveClientUrl(relativeUrl);
    }
}

public class ResolveClientUrlPWebPageRenderingBaseWrapper : ResolveClientUrlWrapper
{
    WebPageRenderingBase _webPageRenderingBase;

    public ResolveClientUrlPWebPageRenderingBaseWrapper(WebPageRenderingBase webPageRenderingBase)
    {
        _webPageRenderingBase = webPageRenderingBase;
    }

    public override string ResolveClientUrl(string relativeUrl)
    {
        return _webPageRenderingBase.Href(relativeUrl);
    }
}

public class ResolveClientUrlUrlHelperWrapper : ResolveClientUrlWrapper
{
    UrlHelper _urlHelper;

    public ResolveClientUrlUrlHelperWrapper(UrlHelper urlHelper)
    {
        _urlHelper = urlHelper;
    }

    public override string ResolveClientUrl(string relativeUrl)
    {
        return _urlHelper.Content(relativeUrl);
    }
}

public class PathUtilityWrapper : ResolveClientUrlWrapper
{
    public override string ResolveClientUrl(string relativeUrl)
    {
        return VirtualPathUtility.ToAbsolute(relativeUrl);
    }
}

You can ResolveClientUrlPageWrapper from classic ASP.NET page or ResolveClientUrlHttpServerUtilityBaseWrapper from ASP.NET MVC controller, ResolveClientUrlUrlHelperWrapper from ASP.NET MVC View. You will have the same background code accross the whole ASP.NET classic and ASP.NET MVC application.



回答3:

I generally do it this way in my javascript code.

var imgUrl = '@Href("~/images/calendar.png")'