ASP.NET MVC Bundle с абсолютными путями
У меня есть виртуальный каталог на IIS, который содержит все файлы JavaScript и CSS. Можно ли включить эти файлы в приложение ASP.NET MVC с помощью Bundles.
Я уже пробовал что-то вроде этого:
bundles.Add(new ScriptBundle("~/bundles/jquery").Include("/public/javascript/jquery-{version}.js"));
но получил ошибку:
Разрешены только относительные URL приложения (~/url).:
/ public / javascript - это виртуальный каталог в IIS.
1 ответ
На самом деле класс Bundle не поддерживает абсолютные пути. Я открыл запрос функции здесь.
Я решил эту проблему с помощью пользовательского VirtualPathProvider и контроллера. Но это очень хрупкая реализация. Вы можете изменить то, что вам нужно.
public class ModuleScriptProvider : VirtualPathProvider
{
public static IBundleModule GetModulePath(string moduleName)
{
//return the absolute or relative path.
}
public static void ParseVirtualPath(string virtualPath, out string moduleName, out string path)
{
var parts = virtualPath.Replace("~/", "").Split('/').Where(p => !string.IsNullOrEmpty(p)).Skip(1).ToList();
if (parts.Count < 2 || !virtualPath.EndsWith(".js"))
throw new FileNotFoundException("Script file doesn't found in the module script directory", virtualPath);
moduleName = parts.First(); // ~/ModuleScript/ModuleName/....
path = string.Join(@"\", parts.Skip(1));
}
public static string MapPathMethod(string virtualPath)
{
if (IsModuleScriptPath(virtualPath))
{
string moduleName;
string path;
ParseVirtualPath(virtualPath, out moduleName, out path);
var moduleDir = GetModulePath(moduleName); //absolute path
if (!moduleDir.EndsWith(@"\"))
moduleDir += @"\";
return moduleDir + path;
}
return HttpContext.Current.Server.MapPath(virtualPath);
}
public static bool IsModuleScriptPath(string virtualPath)
{
String checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
return checkPath.StartsWith("~/ModuleScript/", StringComparison.InvariantCultureIgnoreCase);
}
public override bool FileExists(string virtualPath)
{
return (IsModuleScriptPath(virtualPath) || base.FileExists(virtualPath));
}
public override VirtualFile GetFile(string virtualPath)
{
if (IsModuleScriptPath(virtualPath))
return new ModuleScriptVirtualFile(virtualPath);
return base.GetFile(virtualPath);
}
public override CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
{
if (IsModuleScriptPath(virtualPath))
{
string moduleName;
string path;
ParseVirtualPath(virtualPath, out moduleName, out path);
var bundleModulePath = GetModulePath(moduleName);
return new CacheDependency(bundleModulePath);
}
return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
public override string CombineVirtualPaths(string basePath, string relativePath)
{
return base.CombineVirtualPaths(basePath, relativePath);
}
}
class ModuleScriptVirtualFile : VirtualFile
{
private readonly string _path;
private readonly string _moduleName;
public ModuleScriptVirtualFile(string virtualPath)
: base(virtualPath)
{
ModuleScriptProvider.ParseVirtualPath(virtualPath, out _moduleName, out _path);
}
public override Stream Open()
{
var moduleDir = ModuleScriptProvider.GetModulePath(_moduleName);
if (!moduleDir.EndsWith(@"\"))
moduleDir += @"\";
return new FileStream(moduleDir + _path, FileMode.Open);
}
}
контроллер:
public class ModuleScriptController : Controller
{
public FileStreamResult GetFile(string path)
{
return new FileStreamResult(new ModuleScriptProvider().GetFile("~/ModuleScript/" + path).Open(), "text/javascript");
}
}
В методе Global.asax Application_Start:
HostingEnvironment.RegisterVirtualPathProvider(new ModuleScriptProvider());
BundleTable.EnableOptimizations = true;
BundleTable.MapPathMethod = ModuleScriptProvider.MapPathMethod;
Боже, скорость.