DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • Why Angular and ASP.NET Core Make a Winning Team
  • Role of C# in Building Dynamic and Secure Web Applications
  • PHP or ASP.NET: Which Powerhouse Platform Prevails for Your Next Project?
  • List of Dot Net Interview Questions

Trending

  • Cognitive AI: The Road To AI That Thinks Like a Human Being
  • Performance Optimization Strategies in Highly Scalable Systems
  • Send Your Logs to Loki
  • Breaking Down Silos: The Importance of Collaboration in Solution Architecture
  1. DZone
  2. Coding
  3. Frameworks
  4. ASP.NET Bundling/Minification and Embedded Resources

ASP.NET Bundling/Minification and Embedded Resources

Imran Baloch user avatar by
Imran Baloch
·
Jan. 05, 13 · Interview
Like (12)
Save
Tweet
Share
25.21K Views

Join the DZone community and get the full member experience.

Join For Free

Introduction:

If you want to share your application resources(like css, javascript, images, etc) between different projects then embedded resource is a great choice. Embedded resource is also good for component/control writers because it allows component/control writers to distribute all the application resources with just a single assembly. A lot of vendors are already using this approach. It will great for component/control writers if they can leverage the ASP.NET bundling and minification for improving the performance. So, in this article I will show you how to write a very basic component(helper) which will use the ASP.NET bundling and minification feature on embedded javascript/css files.

Description:

First of all create a new Class Library project and install the Microsoft.AspNet.Mvc, WebActivator and Microsoft ASP.NET Web Optimization Framework 1.1.0-alpha1(make sure to include the -Pre parameter in Package Manager Console) nuget packages. Next, add a reference of System.Web assembly. Then, create your control/component/helper. For demonstration purpose, I will use this sample helper,

public static class HtmlHelpers
        {
            public static MvcHtmlString NewTextBox(this HtmlHelper html, string name)
            {
                var js = Scripts.Render("~/ImranB/Embedded/Js").ToString();
                var css = Scripts.Render("~/ImranB/Embedded/Css").ToString();
                var textbox = html.TextBox(name).ToString();
                return MvcHtmlString.Create(textbox + js + css);
            }
}

In this helper, I am just using a textbox with a style and script bundle. Style bundle include 2 css files and script bundle include 2 js files. So, just create 2 css files(NewTextBox1.css and NewTextBox2.css) and 2 javascript files(NewTextBox1.js and NewTextBox2.js) and then mark these files as embedded resource. Next, add a AppStart.cs file and add the following lines inside this file,

[assembly: WebActivator.PostApplicationStartMethod(typeof(AppStart), "Start")]
        namespace ImranB
        {
            public static class AppStart
            {
                public static void Start()
                {
                    ConfigureRoutes();
                    ConfigureBundles();
                }
                private static void ConfigureBundles()
                {
                    BundleTable.VirtualPathProvider = new EmbeddedVirtualPathProvider(HostingEnvironment.VirtualPathProvider);
                    BundleTable.Bundles.Add(new ScriptBundle("~/ImranB/Embedded/Js")
                        .Include("~/ImranB/Embedded/NewTextBox1.js")
                        .Include("~/ImranB/Embedded/NewTextBox2.js")
                        );
                    BundleTable.Bundles.Add(new StyleBundle("~/ImranB/Embedded/Css")
                        .Include("~/ImranB/Embedded/NewTextBox1.css")
                        .Include("~/ImranB/Embedded/NewTextBox2.css")
                        );
                }
                private static void ConfigureRoutes()
                {
                    RouteTable.Routes.Insert(0,
                        new Route("ImranB/Embedded/{file}.{extension}",
                            new RouteValueDictionary(new { }),
                            new RouteValueDictionary(new { extension = "css|js" }),
                            new EmbeddedResourceRouteHandler()
                        ));
                }
            }
        }

The above class using WebActivator's PostApplicationStartMethod, which allows your assembly to run some code after the Application_Start method of global.asax. The Start method simply register a custom virtual path provider and two bundles which are used in our NewText helper class. But ASP.NET optimization framework will only emit a bundle url when debug="false" or when BundleTable.EnableOptimizations = true. Therefore, we also need to handle the normal javascript and css requests. For this case, the above method has also register a specific route for handling embedded resource requests using EmbeddedResourceRouteHandler route handler. Here is the definition of this handler,

public class EmbeddedResourceRouteHandler : IRouteHandler
        {
            IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
            {
                return new EmbeddedResourceHttpHandler(requestContext.RouteData);
            }
        }
        public class EmbeddedResourceHttpHandler : IHttpHandler
        {
            private RouteData _routeData;
            public EmbeddedResourceHttpHandler(RouteData routeData)
            {
                _routeData = routeData;
            }
            public bool IsReusable
            {
                get { return false; }
            }
            public void ProcessRequest(HttpContext context)
            {
                var routeDataValues = _routeData.Values;
                var fileName = routeDataValues["file"].ToString();
                var fileExtension = routeDataValues["extension"].ToString();
                string nameSpace = typeof(EmbeddedResourceHttpHandler)
                                    .Assembly
                                    .GetName()
                                    .Name;// Mostly the default namespace and assembly name are same
                string manifestResourceName = string.Format("{0}.{1}.{2}", nameSpace, fileName, fileExtension);
                var stream = typeof(EmbeddedResourceHttpHandler).Assembly.GetManifestResourceStream(manifestResourceName);
                context.Response.Clear();
                context.Response.ContentType = "text/css";// default
                if (fileExtension == "js")
                    context.Response.ContentType = "text/javascript";
                stream.CopyTo(context.Response.OutputStream);
            }
        }

EmbeddedResourceRouteHandler returns EmbeddedResourceHttpHandler http handler which will be used to extract embedded resource file from the assembly and then write the file to the response body. Now, the only missing thing is EmbeddedVirtualPathProvider, 


public class EmbeddedVirtualPathProvider : VirtualPathProvider
        {
            private VirtualPathProvider _previous;
            public EmbeddedVirtualPathProvider(VirtualPathProvider previous)
            {
                _previous = previous;
            }
            public override bool FileExists(string virtualPath)
            {
                if (IsEmbeddedPath(virtualPath))
                    return true;
                else
                    return _previous.FileExists(virtualPath);
            }
            public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
            {
                if (IsEmbeddedPath(virtualPath))
                {
                    return null;
                }
                else
                {
                    return _previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
                }
            }
            public override VirtualDirectory GetDirectory(string virtualDir)
            {
                return _previous.GetDirectory(virtualDir);
            }
            public override bool DirectoryExists(string virtualDir)
            {
                return _previous.DirectoryExists(virtualDir);
            }
            public override VirtualFile GetFile(string virtualPath)
            {
                if (IsEmbeddedPath(virtualPath))
                {
                    string fileNameWithExtension = virtualPath.Substring(virtualPath.LastIndexOf("/") + 1);
                    string nameSpace = typeof(EmbeddedResourceHttpHandler)
                                    .Assembly
                                    .GetName()
                                    .Name;// Mostly the default namespace and assembly name are same
                    string manifestResourceName = string.Format("{0}.{1}", nameSpace, fileNameWithExtension);
                    var stream = typeof(EmbeddedVirtualPathProvider).Assembly.GetManifestResourceStream(manifestResourceName);
                    return new EmbeddedVirtualFile(virtualPath, stream);
                }
                else
                    return _previous.GetFile(virtualPath);
            }
            private bool IsEmbeddedPath(string path)
            {
                return path.Contains("~/ImranB/Embedded");
            }
        }

    public class EmbeddedVirtualFile : VirtualFile
    {
        private Stream _stream;
        public EmbeddedVirtualFile(string virtualPath, Stream stream)
            : base(virtualPath)
        {
            _stream = stream;
        }
        public override Stream Open()
        {
            return _stream;
        }
    } 

EmbeddedVirtualPathProvider class is self explanatory. It simply maps a bundling url(used above) and return the embedded request as stream. Note, this class will be invoked by ASP.NET optimization framework during bundling and minifying process. Now, just build your component/control/helper assembly. Then, create a sample ASP.NET(MVC) application and then use this component/control/helper in your page. For example, like,


@using ImranB.Helpers
@Html.NewTextBox("New")

Summary:

In this article, I showed you how to create a component/control/helper that leverage the ASP.NET Optimization framework. A sample application is available at github for download. Hopefully you will enjoy my this article too.

ASP.NET

Published at DZone with permission of Imran Baloch, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Why Angular and ASP.NET Core Make a Winning Team
  • Role of C# in Building Dynamic and Secure Web Applications
  • PHP or ASP.NET: Which Powerhouse Platform Prevails for Your Next Project?
  • List of Dot Net Interview Questions

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: