Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I've created a Visual Studio SharePoint 2010 solution with an ASCX that adds some JavaScript files and CSS to the head of each page; this is based on this article. When I deploy the solution, it adds the files to the correct server folder:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\CustomPageHead

But then the files aren't added to the page headers. I've gone in and activated the user control from the site features but this hasn't fixed it. Here's the simple code in the CustomPageHead.ascx.cs file; I removed the JS files to see if that was causing the issue:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;

namespace CustomPageHead.CONTROLTEMPLATES
{
    public partial class CustomPageHead : UserControl
    {

        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected override void OnInit(EventArgs e)
        {

            Page.Init += delegate(object sender, EventArgs e_Init)
            {
                string SiteURL = SPContext.Current.Web.Url;

                Page.Header.Controls.Add(new LiteralControl(
            "<link rel=\"stylesheet\" type=\"text/css\" href=\""
            + SiteURL + "/_layouts/CustomPageHead/custom.css\" />"));

                Page.Header.Controls.Add(new LiteralControl(
            "<meta name=\"keywords\" content=\"sharepoint,c-sharp\" />"));
            };

            base.OnInit(e);
        }
    }
}

Could it be that I'm trying to activate the feature from a site such as http://mydomain.org/mysite/ and the path in the code above is looking at the current site's root? But why isn't it at least adding the control to the page, even if it has the wrong path?

share|improve this question
add comment

2 Answers

up vote 18 down vote accepted

As James mentioned, your main mistake is that you are using Page.Header.Controls. It is much simplier: this.Controls works like a charm.

If it will not work, you should then check your delegate control declaration XML code. It should look like this:

<Control Id="AdditionalPageHead" Sequence="1000" ControlSrc="~/_controltemplates/MyCompany/AdditionalPageHead.ascx" />

Lastly, I'd recommend you to use native SharePoint controls: CssRegistration and ScriptLink, instead of LiteralControl approach for this purpose.

For example, here is the working code:

    protected override void CreateChildControls()
    {
        base.CreateChildControls();

        this.Controls.Add(new ScriptLink()
            {
                Name = "/_layouts/MyCompany/MyScript.js",
                Language = "javascript",
                Localizable = false
            });

        this.Controls.Add(new CssRegistration()
            {
                Name = "/_layouts/MyCompany/MyStyles.css"
            });
    }

Btw, by using CssRegistration, you could hit the branding bonus, because this approach will allow you to use themable css files, like this:

    protected override void CreateChildControls()
    {
        base.CreateChildControls();
        this.Controls.Add(new CssRegistration() { Name = "/Style Library/Themable/MyCompany/MyStyles.css", EnableCssTheming = true });

    }
share|improve this answer
    
Thanks, omlin. The problem also was I had missed one of the steps in creating the solution as described in the article. Also, what does the base.CreateChildControls() do in the two method overrides above? –  Alex C Sep 1 '11 at 8:51
2  
Base method call it is not obligatory in this particular case, you can safely clear if off. Visual Studio generates it by default :) –  Andrey Markeev Sep 1 '11 at 9:13
    
Thanks, Omlin. Very useful stuff. –  Alex C Sep 1 '11 at 12:11
2  
+1 for CssRegistration. It has an "After" property, where you specify the name of the CSS file after which you want yours to load. This lets you cascade the styles correctly and predictably. This property is new SP2010. –  James Love Sep 1 '11 at 12:40
    
Thanks for your notice, James! Yep, using native controls often delivers some honey drops :) –  Andrey Markeev Sep 1 '11 at 14:34
show 1 more comment

Hm.

What I would do is do the work in CreateChildControls. Have it just add the two LiteralControls to the this.Controls collection.

Then, add your ASCX to the AdditionalPageHead delegate control via your Feature. (step 33 in that article you linked to).

There is a reason (and at this time in the morning I can't remember what it is), but the Page.Header control never did add my controls for me. Add them to this.Controls and do it in CreateChildControls and it'll probably work fine.

This is the method I use to add CSS and jQuery libraries to all my branding projects.

share|improve this answer
    
Thanks, James. What's the diff between this.Controls and Page.Header.Controls? Is it a shortcut? I'm learning more and more by posting here and thanks to all the folks who reply, like yourself :) –  Alex C Sep 1 '11 at 12:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.