Ejemplo n.º 1
0
        /// <summary>
        /// Calls the ContentPlaceHolderHeadRepair.Repair method
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            //Parses link, meta, and script tags that got missed by the Head>CPH bug.
            ContentPlaceHolderFixes.RepairPageHeader(this);

            //Fire the events later
            base.OnLoad(e);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Reparses meta and link tags that weren't parsed correctly the first time.
        /// Only works inside ContentPlaceHolder controls located inside the head.
        /// 1) Parses literal controls: looks for self-closing and empty meta, link, and script controls.
        /// Supports Visible and EnableViewState attributes correctly. EnableViewState=false if not specified.
        /// The TemplateControl is re-calculated.
        /// 2) Parses HtmlGenericControls (link, meta, script tags with runat="server"). HtmlGenericControl instances for 'script' can
        /// only exist if added through code, since &lt;script runat="server"&gt; is for server side code. Supports it anyway :)
        /// Supports Visible and EnableViewState attributes correctly. EnableViewState=false if not specified.
        /// The TemplateControl is re-calculated.
        /// Note: script references don't have a built-in control, so we use a custom ScriptReference instance to provide the rebasing support.
        /// </summary>
        /// <param name="p"></param>
        public static void RepairPageHeader(Page p)
        {
            //Aquire a collection of references to each contentplaceholder in the Head section.
            //ContentPlaceHolders do not account for being located in an HtmlHead, and simply
            //perform the normal parsing logic. We will patch this by iterating through incorrectly identified tags such as
            //<link> and <meta>, and replacing them with the proper control type.
            //As a bonus, we also make script references work, but that is an extra - Head doesn't usually do anything special
            //with those anyway.

            //Note that each contentplaceholder usually contains a child ContentPlaceHolder
            if (p.Header != null)
            {
                ////////////////////// Literal parsing //////////////////////////////
                //Get a collection of all of the LiteralControls in the head
                //This will handle link, meta, and script includes
                List <LiteralControl> toParse = ControlUtils.GetControlsOfType <LiteralControl>(p.Header);

                //handle literal links
                if (toParse != null)
                {
                    foreach (LiteralControl lc in toParse)
                    {
                        //if the literal is directly inside a content tag, on a content page, the TemplateControl property will
                        //incorrectly point to the MasterPage.
                        //So if we use lc.AppRelativeTemplateSourceDirectory, it doesn't work
                        //However, if we use this.AppRelativeTemplateSourceDirectory and
                        //we have a MasterPage>MasterPage(with relative literal stylesheet reference)>Page
                        //Then the relative stylesheet reference will be broke, relative to the Page.

                        //The solution is to find the child TemplateControl of lc's nearest ContentPlaceHolder parent.
                        //We do this before ParseLiteral control, because this value will be propogated to the
                        //component controls.
                        lc.TemplateControl = ContentPlaceHolderFixes.GetAdjustedParentTemplateControl(lc);

                        //Parse literal control
                        Control c = ParseLiteralControl(lc, lc.Text);
                        //notused:  //Article.SetPathRecursive(c, getAdjustedParent(lc).AppRelativeTemplateSourceDirectory);//used to be this.
                        //Replace
                        lc.Parent.Controls.AddAt(lc.Parent.Controls.IndexOf(lc), c);
                        lc.Parent.Controls.Remove(lc);
                    }
                }

                //handle links with runat="server"
                //We just want the outermost cphs
                List <ContentPlaceHolder> cphList = ControlUtils.GetControlsOfType <ContentPlaceHolder>(p.Header, false, true);

                if (cphList != null)
                {
                    //There may be multiple CPHs in the head section
                    foreach (ContentPlaceHolder cph in cphList)
                    {
                        //Get a collection of all of the HtmlGenericControls in the current ContentPlaceHolder.
                        List <HtmlGenericControl> toFix = ControlUtils.GetControlsOfType <HtmlGenericControl>(cph);
                        if (toFix == null)
                        {
                            continue;
                        }

                        //This will handle all link tags, meta tags, or script tags with runat="server"
                        //Also affects script tags parsed in above section (URL resolution)

                        //Iterate through the collection, replacing or modifying the neccesary objects.
                        foreach (HtmlGenericControl hgc in toFix)
                        {
                            HtmlControl replacement = null;
                            switch (hgc.TagName.ToLower())
                            {
                            case "link":
                                //Create a replacement HtmlLink object with identical attributes.
                                //HtmlLink will resolve virtual URLs on the href attribute at render-time, unlike HtmlGenericControl.
                                replacement = new HtmlLink();

                                break;

                            case "meta":
                                //Create a replacement HtmlMeta object with identical attributes.
                                replacement = new HtmlMeta();
                                break;

                            case "script":
                                //Create a new script reference, which resolves the src attribute at render-time
                                replacement = new ScriptReference();
                                break;
                            }


                            if (replacement != null)
                            {
                                //Adjust the TemplateControl for the *other* ContentPlaceHolder bug.
                                replacement.TemplateControl = GetAdjustedParentTemplateControl(hgc.TemplateControl);

                                //Turn off ViewState
                                replacement.EnableViewState = false;

                                //Copy attributes
                                foreach (string s in hgc.Attributes.Keys)
                                {
                                    string val = hgc.Attributes[s];
                                    replacement.Attributes.Add(s, val);
                                }
                                //Assign known properties that aren.t collection-backed
                                replacement.EnableViewState = hgc.EnableViewState;
                                replacement.Visible         = hgc.Visible;

                                //Insert the new object next to the old, then remove the old.
                                hgc.Parent.Controls.AddAt(hgc.Parent.Controls.IndexOf(hgc), replacement);
                                hgc.Parent.Controls.Remove(hgc);
                            }
                        }
                    }
                }
            }


            /* Analyize TemplateControls. Prints TemplateControl/TemplateSourceDirectory tree for diagnostics.
             *  List<Control> allcontrols = GetControlsOfType<Control>(this);
             *  List<TemplateControl> uniqueTemplateControls =new List<TemplateControl>();
             *  Debug.WriteLine(Page.AppRelativeTemplateSourceDirectory);
             *  foreach (Control c in allcontrols)
             *  {
             *      //Debug.WriteLine(c.ID + "   (" + c.TemplateControl.ID + ") - " + c.AppRelativeTemplateSourceDirectory);
             *      if (!uniqueTemplateControls.Contains(c.TemplateControl)){
             *          uniqueTemplateControls.Add(c.TemplateControl);
             *          string s = c.TemplateSourceDirectory;
             *      }
             *
             *  }
             *  StringWriter sw = new StringWriter();
             *  PrintTree(this.Header, 0, sw);
             *  this.Header.Controls.AddAt(0, new LiteralControl(Server.HtmlEncode((sw.ToString()))));
             */
        }