2

I want to get the bundles build's string in other environment, eg:HttpApplication start, Console application, etc.

But when I call

Scripts.Render("~/js").ToHtmlString()

Will be throw a Exception:

Value cannot be null.
Parameter name: httpContext

How to mock it to get result?

Matt
  • 21,449
  • 14
  • 100
  • 149
Zack Yang
  • 389
  • 1
  • 11

1 Answers1

1

Short answer: No, it is not possible to use Scripts.Render without httpContext. But there might be a workaround, if you're willing to mock it (see below).

Detailed answer: Microsoft made some unfortunate design decisions. I have decompiled the Render method of the System.Web.Optimization (V1.1.0.0) library (part of the Microsoft.ASP.NET Web Optimization Framework, available via NUGET) and found: Scrips.Render (which calls Scripts.RenderFormat internally) calls Scripts.Manager.RenderExplicit(tagFormat, paths) to return the rendering result.

That function uses this.DeterminePathsToRender(paths) internally to resolve the paths by using this.ResolveVirtualPath(current). And if you take a look at it you'll see, that it uses this._httpContext to resolve the path:

internal string ResolveVirtualPath(string virtualPath)
{
    Uri uri;
    if (Uri.TryCreate(virtualPath, UriKind.Absolute, out uri))
    {
        return virtualPath;
    }
    string arg = "";
    if (this._httpContext.Request != null)
    {
        arg = this._httpContext.Request.AppRelativeCurrentExecutionFilePath;
    }
    return this.ResolveUrlMethod(arg, virtualPath);
}

So unfortunately there is no way around httpContext. Another way I thought of was to inherit a class myScriptClass from class Scripts and then set the internal property Context via the myScriptClass constructor. But that is also not possible because Scripts is a static class which you can't inherit from (see this topic for details).


But you can use BundleContext.HttpContext to get or set the currently used HttpContext.

However, if you have only access to a particular BundleCollection object, then you have no option since its .Context property is internal.

For a console application this means that you might have to create a fake request object and HttpContext, which you have to assign to BundleContext.HttpContext before you're using the render method. You can look here or there to get more details how to do that.

Matt
  • 21,449
  • 14
  • 100
  • 149