ASP.NET捆绑/缩小:包括动态生成的Javascript(ASP.NET bundling/mi

2019-06-27 03:50发布

我有一个动态生成的Javascript的站点。 生成的代码描述型的元数据和一些服务器端的常量,使客户能够轻松地使用服务器的服务 - 所以这是非常缓存。

所生成的Javascript由ASP.NET MVC控制器服务; 因此它具有URI; 说~/MyGeneratedJs

我想加入此JavaScript与其他静态Javascript文件(如jQuery的等等),一个Javascript包:所以就像静态文件,我希望它在调试模式,并与在非其他文件捆绑缩小的形式分别引用调试模式。

我怎样才能在一个包包括动态生成的JavaScript?

Answer 1:

达林是正确的,目前捆绑只适用于静态文件。 但是,如果你可以用最新的内容添加一个占位符文件,不捆绑安装文件更改通知,它会自动检测占位符文件发生更改时。

此外,我们将要移动使用VirtualPathProviders很快,这可能是服务于动态生成的内容的方式。

更新:1.1-α1的释放,现在是哪个有VPP的支持



Answer 2:

随着VirtualPathProviders这成为可能。 动态内容到捆扎工艺集成需要以下几个步骤:

  1. 写请求/构建所需内容的逻辑。 从控制器生成的内容直接需要一些工作:

     public static class ControllerActionHelper { public static string RenderControllerActionToString(string virtualPath) { HttpContext httpContext = CreateHttpContext(virtualPath); HttpContextWrapper httpContextWrapper = new HttpContextWrapper(httpContext); RequestContext httpResponse = new RequestContext() { HttpContext = httpContextWrapper, RouteData = RouteTable.Routes.GetRouteData(httpContextWrapper) }; // Set HttpContext.Current if RenderActionToString is called outside of a request if (HttpContext.Current == null) { HttpContext.Current = httpContext; } IControllerFactory controllerFactory = ControllerBuilder.Current.GetControllerFactory(); IController controller = controllerFactory.CreateController(httpResponse, httpResponse.RouteData.GetRequiredString("controller")); controller.Execute(httpResponse); return httpResponse.HttpContext.Response.Output.ToString(); } private static HttpContext CreateHttpContext(string virtualPath) { HttpRequest httpRequest = new HttpRequest(string.Empty, ToDummyAbsoluteUrl(virtualPath), string.Empty); HttpResponse httpResponse = new HttpResponse(new StringWriter()); return new HttpContext(httpRequest, httpResponse); } private static string ToDummyAbsoluteUrl(string virtualPath) { return string.Format("http://dummy.net{0}", VirtualPathUtility.ToAbsolute(virtualPath)); } } 
  2. 实现一个包装现有的虚拟路径提供者和拦截应提供动态内容的所有虚拟路径。

     public class ControllerActionVirtualPathProvider : VirtualPathProvider { public ControllerActionVirtualPathProvider(VirtualPathProvider virtualPathProvider) { // Wrap an existing virtual path provider VirtualPathProvider = virtualPathProvider; } protected VirtualPathProvider VirtualPathProvider { get; set; } public override string CombineVirtualPaths(string basePath, string relativePath) { return VirtualPathProvider.CombineVirtualPaths(basePath, relativePath); } public override bool DirectoryExists(string virtualDir) { return VirtualPathProvider.DirectoryExists(virtualDir); } public override bool FileExists(string virtualPath) { if (ControllerActionHelper.IsControllerActionRoute(virtualPath)) { return true; } return VirtualPathProvider.FileExists(virtualPath); } public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) { AggregateCacheDependency aggregateCacheDependency = new AggregateCacheDependency(); List<string> virtualPathDependenciesCopy = virtualPathDependencies.Cast<string>().ToList(); // Create CacheDependencies for our virtual Controller Action paths foreach (string virtualPathDependency in virtualPathDependenciesCopy.ToList()) { if (ControllerActionHelper.IsControllerActionRoute(virtualPathDependency)) { aggregateCacheDependency.Add(new ControllerActionCacheDependency(virtualPathDependency)); virtualPathDependenciesCopy.Remove(virtualPathDependency); } } // Aggregate them with the base cache dependency for virtual file paths aggregateCacheDependency.Add(VirtualPathProvider.GetCacheDependency(virtualPath, virtualPathDependenciesCopy, utcStart)); return aggregateCacheDependency; } public override string GetCacheKey(string virtualPath) { return VirtualPathProvider.GetCacheKey(virtualPath); } public override VirtualDirectory GetDirectory(string virtualDir) { return VirtualPathProvider.GetDirectory(virtualDir); } public override VirtualFile GetFile(string virtualPath) { if (ControllerActionHelper.IsControllerActionRoute(virtualPath)) { return new ControllerActionVirtualFile(virtualPath, new MemoryStream(Encoding.Default.GetBytes(ControllerActionHelper.RenderControllerActionToString(virtualPath)))); } return VirtualPathProvider.GetFile(virtualPath); } public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies) { return VirtualPathProvider.GetFileHash(virtualPath, virtualPathDependencies); } public override object InitializeLifetimeService() { return VirtualPathProvider.InitializeLifetimeService(); } } public class ControllerActionVirtualFile : VirtualFile { public CustomVirtualFile (string virtualPath, Stream stream) : base(virtualPath) { Stream = stream; } public Stream Stream { get; private set; } public override Stream Open() { return Stream; } } 

    您还可以,如果你需要它来实现的CacheDependency:

     public class ControllerActionCacheDependency : CacheDependency { public ControllerActionCacheDependency(string virtualPath, int actualizationTime = 10000) { VirtualPath = virtualPath; LastContent = GetContentFromControllerAction(); Timer = new Timer(CheckDependencyCallback, this, actualizationTime, actualizationTime); } private string LastContent { get; set; } private Timer Timer { get; set; } private string VirtualPath { get; set; } protected override void DependencyDispose() { if (Timer != null) { Timer.Dispose(); } base.DependencyDispose(); } private void CheckDependencyCallback(object sender) { if (Monitor.TryEnter(Timer)) { try { string contentFromAction = GetContentFromControllerAction(); if (contentFromAction != LastContent) { LastContent = contentFromAction; NotifyDependencyChanged(sender, EventArgs.Empty); } } finally { Monitor.Exit(Timer); } } } private string GetContentFromControllerAction() { return ControllerActionHelper.RenderControllerActionToString(VirtualPath); } } 
  3. 注册您的虚拟路径提供:

     public static void RegisterBundles(BundleCollection bundles) { // Set the virtual path provider BundleTable.VirtualPathProvider = new ControllerActionVirtualPathProvider(BundleTable.VirtualPathProvider); bundles.Add(new Bundle("~/bundle") .Include("~/Content/static.js") .Include("~/JavaScript/Route1") .Include("~/JavaScript/Route2")); } 
  4. 可选:添加智能感知支持你的观点。 使用<script>标记您的视图中,并让他们通过定制的ViewResult被删除:

     public class DynamicContentViewResult : ViewResult { public DynamicContentViewResult() { StripTags = false; } public string ContentType { get; set; } public bool StripTags { get; set; } public string TagName { get; set; } public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } if (string.IsNullOrEmpty(ViewName)) { ViewName = context.RouteData.GetRequiredString("action"); } ViewEngineResult result = null; if (View == null) { result = FindView(context); View = result.View; } string viewResult; using (StringWriter viewContentWriter = new StringWriter()) { ViewContext viewContext = new ViewContext(context, View, ViewData, TempData, viewContentWriter); View.Render(viewContext, viewContentWriter); if (result != null) { result.ViewEngine.ReleaseView(context, View); } viewResult = viewContentWriter.ToString(); // Strip Tags if (StripTags) { string regex = string.Format("<{0}[^>]*>(.*?)</{0}>", TagName); Match res = Regex.Match(viewResult, regex, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline | RegexOptions.Singleline); if (res.Success && res.Groups.Count > 1) { viewResult = res.Groups[1].Value; } else { throw new InvalidProgramException( string.Format("Dynamic content produced by View '{0}' expected to be wrapped in '{1}' tag.", ViewName, TagName)); } } } context.HttpContext.Response.ContentType = ContentType; context.HttpContext.Response.Output.Write(viewResult); } } 

    使用扩展方法或添加辅助函数来你的控制器:

     public static DynamicContentViewResult JavaScriptView(this Controller controller, string viewName, string masterName, object model) { if (model != null) { controller.ViewData.Model = model; } return new DynamicContentViewResult { ViewName = viewName, MasterName = masterName, ViewData = controller.ViewData, TempData = controller.TempData, ViewEngineCollection = controller.ViewEngineCollection, ContentType = "text/javascript", TagName = "script", StripTags = true }; } 

这些步骤是similiar其他类型的动态内容。 见捆绑和缩小和嵌入式资源的例子。

我加了概念库的证明GitHub的 ,如果你想尝试一下。



Answer 3:

这是不可能的。 束只静态文件。



文章来源: ASP.NET bundling/minification: including dynamically generated Javascript