ASP.net: User Control Specific CSS/JS Loading

(Update: the BaseUserControl class has been updated to handle loading specific CSS or JS files or one or the other. This allows a common CSS or JS file to be passed for a set of controls making up a module within your application.)

(Update: The BaseUserControl class has been updated to handle instances where your UserControl is loaded multiple times on the same page. This will stop the CSS and JS from being loaded multiple times for each control.)

(Update: If your pages are using MasterPages for their designs make sure you add a runat=”server” to the head tag of your master pages. If you do not the Header property of the page will be null. )

In ASP.net we run into an issue when it comes our User Controls and their corresponding CSS loading in the main CSS files even when that User Control is not included in the 90% of the pages a user calls. (this is the same with JavaScript files)

In order to make sure that my User Control’s CSS is not unnecessarily loaded in the application’s main CSS file and to maintain a little more order in my design I like to use a little programming magic. This magic allows me to only load the CSS for a User Control when it is included in a page or another User Control.

To accomplish this magic I create a Base User Control from which all my User Controls inherit. This base control contains a method called LoadResources which does the following:

  1. Pulls the name of the Current Control making the call.
  2. Adds a Link tag with the path to the CSS file for the current control
  3. Adds a Script tag with the path to the JavaScript file for the current control

(All of the above are based on the CSS and JavaScript files having the same name as the control and those files being located in the same location as the current control.)

Code:

public class BaseUserControl : UserControl

{

    #region Private Fields

    private string _controlName;

    #endregion

    #region Protected Methods

    /// 

    /// Used if the control has custom CSS or Javascript

    /// which needs to be loaded with the control.

    /// The resources consist of a .css and .js files 

    /// which have the same name as the control. This method

    /// will search the control's location for those 2

    /// files and add them as CSS and Javascript links to

    /// the control's ascx content.

    /// 

    protected void LoadResources()

    {

        PullControlName();

        LoadCssFile();

        LoadJsFile();

    }

    /// 

    /// Loads the resources.

    /// 

    /// Name of the file.

    /// Type of the file.

    protected void LoadResources(string fileName, FileType fileType)

    {

        switch (fileType)

        {

            case FileType.Script:

                LoadJsFile(fileName);

                break;

            case FileType.Style:

                LoadCssFile(fileName);

                break;

        }

    }

    /// 

    /// Loads the resources.

    /// 

    /// 
styleFileName">
Name of the style file.

    /// 
scriptFileName">
Name of the script file.

    protected void LoadResources(string styleFileName, string scriptFileName)

    {

        LoadCssFile(styleFileName);

        LoadJsFile(scriptFileName);

    }

    #endregion

    #region Private Methods

    private void PullControlName()

    {

        string controlType = GetType().ToString();

        List<string> controlParts = controlType.Split('_').ToList();

        if (controlParts.Count > 0)

        {

            if (!string.IsNullOrEmpty(controlParts[controlParts.Count - 2]))

            {

                _controlName = controlParts[controlParts.Count - 2];

            }

        }

    }

    private void LoadCssFile()

    {

        try

        {

            // Injects the CSS for this control into the page header

            string cssUrl = ResolveUrl(_controlName + ".css");

            string cssPath = cssUrl.Remove(0, 1).Replace('/', '\\');

            if (File.Exists(Request.PhysicalApplicationPath + cssPath))

            {

                string controlId = _controlName + "Style";

                if (!DoesControlExist(controlId))

                {

                    HtmlLink css = new HtmlLink();

                    css.ID = controlId;

                    css.Href = cssUrl;

                    css.Attributes.Add("rel", "stylesheet");

                    css.Attributes.Add("type", "text/css");

                    Page.Header.Controls.Add(css);

                }

            }

        }

        catch (Exception ex)

        {

            //TODO: Handle exception as a warning

        }

    }

    private void LoadCssFile(string fileName)

    {

        try

        {

            // Injects the CSS for this control into the page header

            string cssUrl = ResolveUrl(fileName);

            string cssPath = cssUrl.Remove(0, 1).Replace('/', '\\');

            if (File.Exists(Request.PhysicalApplicationPath + cssPath))

            {

                string controlId = fileName + "Style";

                if (!DoesControlExist(controlId))

                {

                    HtmlLink css = new HtmlLink();

                    css.ID = controlId;

                    css.Href = cssUrl;

                    css.Attributes.Add("rel", "stylesheet");

                    css.Attributes.Add("type", "text/css");

                    Page.Header.Controls.Add(css);

                }

            }

        }

        catch (Exception ex)

        {

            //TODO: Handle exception as a warning

        }

    }

    private void LoadJsFile()

    {

        try

        {

            // Injects the JavaScript for this control into the page header

            string jsUrl = ResolveUrl(_controlName + ".js");

            string jsPath = jsUrl.Remove(0, 1).Replace('/', '\\');

            if (File.Exists(Request.PhysicalApplicationPath + jsPath))

            {

                string controlId = _controlName + "Script";

                if (!DoesControlExist(controlId))

                {

                    HtmlGenericControl js = new HtmlGenericControl("script");

                    js.ID = controlId;

                    js.Attributes.Add("type", "text/javascript");

                    js.Attributes.Add("src", jsUrl);

                    Page.Header.Controls.Add(js);

                }

            }

        }

        catch (Exception ex)

        {

            //TODO: Handle exception as a warning

        }

    }

    private void LoadJsFile(string fileName)

    {

        try

        {

            // Injects the JavaScript for this control into the page header

            string jsUrl = ResolveUrl(fileName);

            string jsPath = jsUrl.Remove(0, 1).Replace('/', '\\');

            if (File.Exists(Request.PhysicalApplicationPath + jsPath))

            {

                string controlId = fileName + "Script";

                if (!DoesControlExist(controlId))

                {

                    HtmlGenericControl js = new HtmlGenericControl("script");

                    js.ID = controlId;

                    js.Attributes.Add("type", "text/javascript");

                    js.Attributes.Add("src", jsUrl);

                    Page.Header.Controls.Add(js);

                }

            }

        }

        catch (Exception ex)

        {

            //TODO: Handle exception as a warning

        }

    }

    private bool DoesControlExist(string controlId)

    {

        object control = Page.Header.FindControl(controlId);

        if (control != null)

            return true;

        return false;

    }

    #endregion

    #region Utility Classes

    /// 

    /// Types of files which are accepted by the 

    /// resource loader.

    /// 

    public enum FileType

    {

        /// 

        /// Cascading Style Sheet files

        /// 

        Style,

        /// 

        /// JavaScript files

        /// 

        Script

    }

    #endregion

}

Published by

Tim Clark

Experienced Business Owner, Chief Information Officer, Vice President, Chief Software Architect, Application Architect, Project Manager, Software Developer, Senior Web Developer, Graphic Designer & 3D Modeler, University Instructor, University Program Chair, Academic Director. Specialties: Ruby, Ruby on Rails, JavaScript, JQuery, AJAX, Node.js, React.js, Angular.js, MySQL, PostgreSQL, MongoDB, SQL Server, Responsive Design, HTML5, XHTML, CSS3, C#, ASP.net, Project Management, System Design/Architecture, Web Design, Web Development, Adobe CS6 (Photoshop, Illustrator)

Leave a comment