Cssrewriteurltransform with or Without Virtual Directory

CssRewriteUrlTransform with or without virtual directory

I am not sure to fully understand your problem, but seeing http://localhost here seems wrong. You should never use an absolute URL for your bundles.

For me CssRewriteUrlTransform works perfectly, here is how I use it:

bundles.Add(new StyleBundle("~/bundles/css").Include(
"~/Content/css/*.css", new CssRewriteUrlTransform()));

"Bundles" is virtual.

Does this helps?

Update

I was confused with the "VirtualDir" thing, as you are talking about IIS VirtualDir, and I was thinking Bundle VirtualDir! It's true that in this case CssRewriteUrlTransform will rewrite URLs to the Host, not to the Host/VirtualDir URI.

To do that, you have to derive CssRewriteUrlTransform to make it do what you need it to.
There is a good discussion here: ASP.NET MVC4 Bundling with Twitter Bootstrap

Seems the best answer is there:http://aspnetoptimization.codeplex.com/workitem/83

public class CssRewriteUrlTransformWrapper : IItemTransform
{
public string Process(string includedVirtualPath, string input)
{
return new CssRewriteUrlTransform().Process("~" + VirtualPathUtility.ToAbsolute(includedVirtualPath), input);
}
}

Use this class instead of CssRewriteUrlTransform

ASP.NET MVC: StyleBundle IncludeDirectory & CssRewriteUrlTransform

As I didn't find a better answer, I'll post my solution (which feels more like a workaround):

public class BundleConfig {
private class CssRewriteUrlTransformWrapper : IItemTransform {
public string Process(string includedVirtualPath, string input) {
//see https://stackoverflow.com/questions/19765238/cssrewriteurltransform-with-or-without-virtual-directory
return new CssRewriteUrlTransform().Process("~" + VirtualPathUtility.ToAbsolute(includedVirtualPath), input);
}
}

private static string MakeVirtualPath(string fromPhysPath, string withVirtualPath) {
var res = fromPhysPath.Replace("\\", "/");
var idx = res.IndexOf(withVirtualPath.Replace("~", ""));
res = "~" + res.Substring(idx);

return res;
}

private static StyleBundle CreateStyleBundleForDir(string virtualPath) {
StyleBundle res = new StyleBundle(virtualPath + "/bundle");

string[] cssFilesPhysical = Directory.GetFiles(HttpContext.Current.Server.MapPath(virtualPath), "*.css", SearchOption.AllDirectories);

List<string> cssFilesVirtual = new List<string>();
foreach (var file in cssFilesPhysical) {
res.Include(MakeVirtualPath(file, virtualPath), new CssRewriteUrlTransformWrapper());
}

return res;
}

public static void RegisterBundles(BundleCollection bundles) {
bundles.Add(CreateStyleBundleForDir("~/app/custom"));
}
}

I'm open for constructive citicism :)

mvc bundling and relative css image when website is deployed to an application

If there are no virtual directories involved the following code would do:

bundles.Add(new StyleBundle("~/bundles/css").Include(
"~/Content/css/*.css", new CssRewriteUrlTransform()));

but when VirtualDirectory is used CssRewriteUrlTransform will rewrite to Host instead of Host/VirtualDirectory. the solution is to derive CssRewriteUrlTransform which is fully discussed here: ASP.NET MVC4 Bundling with Twitter Bootstrap:

public class CssRewriteUrlTransformWrapper : IItemTransform
{
public string Process(string includedVirtualPath, string input)
{
return new CssRewriteUrlTransform().Process("~" + VirtualPathUtility.ToAbsolute(includedVirtualPath), input);
}
}

MVC Bundling and CSS relative URLs

CssRewriteUrlTransform updates the CSS Url with absolute path, saying so if we use -

bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css",new CssRewriteUrlTransform()));

and we have following CSS class in "site.css"

.Sandy
{
background-image: url("Images/Sandy.jpg");
border: 1px solid #c8c8c8;
border-radius:4px 4px 4px 4px;
box-shadow: 1px 1px 8px gray;
background-position:left;
background-size:contain;
-moz-background-size:contain;
-webkit-background-size:contain;
-o-background-size:contain;
background-repeat:no-repeat;
min-height:100px;
min-width:100px;
display:block;
}

and following folder structure -

   -Web site Root
-Content
--site.css
--Images
---Sandy.jpg

Bundling will generate following CSS Url Path for "background-image" -

 background-image: url("/Content/Images/Sandy.jpg");

And now if you hosting the website / web application as a website on web server above path will work,
because browser will send request for this resource using following Url because of leading '/'

http://<server>/content/images/sandy.jpg

but if you host the website as web application this will create problem. Because browser will still interpret this as absolute Url instead of relative and still send following request to fetch this resource -

   http://<server>/content/images/sandy.jpg

So, the solution for this problem is using the relative Url even in CSS file and then remove the CssRewriteUrlTransform from the Bundle config as below -

background-image: url("Images/Sandy.jpg");

bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));

Avoid adding virtual directory to path on an ASP.NET 5 application

Interestingly , This will work

<img src='~/assets/poster.jpg'/>

But, this won't

<div style="width:990px; height:99px; background-image: url('~/assets/poster.jpg')"> </div>

For your inline style, you can use the Url.Content helper method to generate the application absolute path.

The below code should work.

<div style="width: 100px; height: 100px; 
background-image:url('@Url.Content("~/assets/poster.jpg")')"></div>

If you want it in a css class, you can simply use the relative path.

.myTest {
background-image: url('../assets/gravatar.png');
width:100px;height: 50px;
}

Assuming your css file is under a directory(Ex:css) which is a sibling to assets folder.

Bundling not working for mapped virtual directory

I've done a bit of experimentation and managed to solve it. What doesn't work is pointing the root of the static site to the same root of the main website, as the web.config files are shared - any change (i.e. disabling session state) made to the static site is also applied to the main website.

In the end, what works is the following:

  • Have the static domain point to a separate root folder on the file system.
  • Keep the virtual directories on the static site (/Content/ and /Scripts/) pointing to their corresponding locations on the main site.
  • Since we use Helicon's URL-rewriter for cache-busting, create a bare-bones .htaccess file with the same rule as is used in the main site; put that in the root of the static site.
  • Copy the global.asax file from the main website into the root of the static site. This cannot be a shortcut.
  • Copy the contents of the /bin/ folder from the main website into the static site.
    • A virtual directory in IIS pointing to the /bin/ folder on the main website will NOT work.
    • Creating a shortcut in the file system to the /bin/ folder on the main website also will not work.
  • In IIS, ensure the static site uses its own application pool, and that it's configured for .NET 4.0, Integrated pipeline mode. This is so that the MVC 4 bundling will work.
  • Create a bare-bones web.config with the UrlRoutingModule added.

This is our web.config for the static site:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<customErrors mode="Off">
</customErrors>
<sessionState mode="Off" />
<pages enableSessionState="false" enableViewState="false" enableViewStateMac="false" renderAllHiddenFieldsAtTopOfForm="false" />
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="ScriptModule" />
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</modules>
<urlCompression doStaticCompression="true" doDynamicCompression="true" />
<security>
<requestFiltering allowDoubleEscaping="True" />
</security>
<tracing>
<traceFailedRequests>
<add path="*">
<traceAreas>
<add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" />
</traceAreas>
<failureDefinitions timeTaken="00:00:00" statusCodes="200" />
</add>
</traceFailedRequests>
</tracing>
<!-- Cache static content for a month, only enable on UAT or Live -->
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="30.00:00:00"/>
</staticContent>
</system.webServer>
</configuration>

The main idea is that bundling requires ASP.NET MVC4 to be enabled and running on the static site, since the bundling is evaluated by IIS before the virtual directories are considered (and there doesn't seem a way to reverse that).



Related Topics



Leave a reply



Submit