Author: Tobias Zimmergren
http://www.zimmergren.net | http://www.tozit.com | @zimmergren
Introduction
In this post we’ll take a quick look at some of the new DelegateControls I’ve discovered for SharePoint 2013 and how you can replace or add information to your new master pages using these new controls, without modifying the master pages. This is done exactly the same way as you would do it back in the 2010 projects (and 2007), the only addition in this case are a few new controls that we’ll investigate.
New DelegateControls
Searching through the main master page, Seattle.master, I’ve found these three new DelegateControls:
- PromotedActions
- SuiteBarBrandingDelegate
- SuiteLinksDelegate
So let’s take a look at where these controls are placed on the Master page and how we can replace them.
PromotedActions Delegate Control
The PromotedActions delegate control allows you to add your own content to the following area on a SharePoint site in the top-right section of the page:
![]()
An example of adding an additional link may look like this:
![]()
So what does the files look like for these parts of the project?
Elements.xml
PromotedActions.aspx (User Control)
Post on Facebook (image no longer exists: legacy SharePoint icon from /_layouts)
SuiteBarBrandingDelegate Delegate Control
This DelegateControl will allow you to override the content that is displayed in the top-left corner of every site. Normally, there’s a text reading “SharePoint” like this:
![]()
If we override this control we can easily replace the content here. For example, most people would probably like to add either a logo or at least make the link clickable so you can return to your Site Collection root web. Let’s take a look at what it can look like if we’ve customized it (this is also a clickable logo):
![]()
So what does the files look like for this project?
Elements.xml
SuiteBarBrandingDelegate.ascx (User Control)
This is the only content in my User Control markup:
SuiteBarBrandingDelegate.ascx.cx (User Control Code Behind)
protected void Page*Load(object sender, EventArgs e) { BrandingTextControl.Controls.Add(new Literal { Text = string.Format(“logo: {2}, image: {1}, url: {0}”, SPContext.Current.Site.Url, ”/*layouts/15/images/Zimmergren.DelegateControls/tozit36light.png”, SPContext.Current.Site.RootWeb.Title) }); }
SuiteLinksDelegate Delegate Control
The SuiteLinksDelegate control will allow us to modify the default links, and to add our own links, in the “suit links” section:
![]()
By adding a custom link to the collection of controls, it can perhaps look like this:
![]()
What does the project files look like for modifying the SuiteLinksDelegate? Well, here’s an example:
Elements.xml
SuiteLinksDelegate.aspx.cs (User Control Code Behind)
public partial class SuiteLinksDelegate : MySuiteLinksUserControl { protected override void Render(HtmlTextWriter writer) { writer.RenderBeginTag(HtmlTextWriterTag.Style); writer.Write(“.ms-core-suiteLinkList {display: inline-block;}”); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Class, “ms-core-suiteLinkList”); writer.RenderBeginTag(HtmlTextWriterTag.Ul); // The true/false parameter means if it should be the active link or not - since I’m shooting off this to an external URL, it will never be active.. RenderSuiteLink(writer, “http://timelog.tozit.com”, “Time Report”, “ReportYourTimeAwesomeness”, false); writer.RenderEndTag(); base.Render(writer); } }
Solution overview
For reference: I’ve structured the project in a way where I’ve put all the changes into one single Elements.xml file and they’re activated through a Site Scoped feature called DelegateControls. The solution is a Farm solution and all artifacts required are deployed through this package.
![]()
Summary
In this post we’ve looked at how we can customize some of the areas in a SharePoint site without using master page customizations. We’ve used the good-old approach of hooking up a few Delegate Control overrides to our site collection. Given the approach of Delegate Controls, we can easily just de-activate the feature and all our changes are gone. Simple as that.
In SharePoint 2013 we can still do Delegate Control overrides just like we did back in 2007 and 2010 projects, and it’s still pretty slick. I haven’t investigated any other master pages other than the Seattle.master right now – perhaps there’s more new delegate controls somewhere else. Let’s find out..
Enjoy.
Comments are closed
Archived comments
Great stuff !!! thanks for sharing.
Thank you jignesh.
Beautiful! Thanks for the info and the code! You are a million hours saved!
Thank you AprilLynn, that's a lot of hours right there - glad I could help :-)
It seems I can only scope this at the Farm level. Is it possible to scope to the Web Application or event SPSite?
Hi Bismarck,
You can scope this to Site or Web, which are the two most normal ways to scope these types features.
Just make sure to add the artifacts to a feature that you scope to Web or Site and you're all set.
Cheers,
Tobias.
Can I scope the solution to the SPSite and run this in a sandbox (SharePoint Online)?
Hi Tobias, great post.
I have the same q as Frank, or almost, does this work in SPO 2013? Or is there any special modification needed?
Hi guys, did either of you find out if this worked as a sandboxed solution?
Good post :) Notice that for SuiteBarBrandingDelegate, the HTML is a SPWebApplication property : SPContext.Current.Site.WebApplication.SuiteBarBrandingElementHtml ;-)
I did an admin application page + custom action to edit it to confirm that
Just saw the next post ;-)
Rock and roll :-)
Hey Christian,
Yes I already wrote about that here: http://zimmergren.net/techn...
:-)
For the suite delegate links, any way to have them open in a new window? There is no override for that in RenderSuiteLink..
Hi CBL,
I haven't looked into that myself, but I'm pretty confident it's possible to do one way or the other. Since you can set attributes on your links (like: writer.AddAttribute(HtmlTextWriterAttribute.Class, "ms-core-suiteLinkList"); for example) then perhaps you can tag it with a custom class and have some jQuery magic take care of opening that link in a new window. Shouldn't be too hard to accomplish that.
As for any built-in way to have them open in a new window: I don't know. But what I posted above should be possible.
Cheers,
Tobias.
Hi, good article! Do you think it is possible to add a drop-down menu in
SuiteLinksDelegate- area?
Hi Pieter,
Just like I replied to CBL here below just now, I think you can do that using jQuery quite easily. Have a link render like normal and then append some jQuery and CSS magic on top of that to make a drop down. I don't have any code samples at hand for this right now, but it should absolutely be possible :-)
Cheers,
Tobias.
Thanks very much, this article makes my branding work much more easier. I was using css to cover the suitebar text. but it is still there when the page is loading.
Hi Jude,
I'm glad you liked it.
Cheers,
Tobias.
A shame that SuiteLinksDelegate is not really extensible. This solution breaks the semantics of the outputted HTML putting two UL's after another, instead of letting us actually add LI elements to the parent unordered list of links. (hence the style-trick with inline-block, of course). Would have been nice if the delegatecontrol had allowed multiple controls instead, or another way to inject our own links "inline".
Just saw this comment mate :-)
jQuery can fix anything, but I agree that the servercontrols should be able to output nicer HTML for us by default.
Great post!
Thank you Wes, appreciated.
Tob.
Hi,
I've just apply your method to add a custom link to suite bar links but after deploying suite bar links go hidden and I can't bring them back to my site....Any help or idea ?
thanks in advance.
Hi Mahdi,
That doesn't sound very good :-)
Can you please reproduce the steps and share the code you've used so I know what you've done?
None of the code in my article actually removes anything - it only replaces or adds things with your own custom controls. What differs your implementation from any of the above?
Cheers,
Tobias.
Hi,
Even I followed the same on this article. It was working good in the development environment, not in the production. Once I activate the feature, all of the suite bar links are gone.
Looks like something is broken.
Hi Tobias,
The code that I used in my project is exactly as same as yours but the only part that I think makes difference is RenderSuiteLink function. Here is the code that I use for this function:
protected static void RenderSuiteLink(HtmlTextWriter writer, string url, string name, string linkId)
{
writer.AddAttribute(HtmlTextWriterAttribute.Class, "ms-core-suiteLink");
writer.RenderBeginTag(HtmlTextWriterTag.Li);
writer.AddAttribute(HtmlTextWriterAttribute.Class, "ms-core-suiteLink-a");
writer.AddAttribute(HtmlTextWriterAttribute.Href, url);
writer.AddAttribute(HtmlTextWriterAttribute.Id, linkId);
writer.RenderBeginTag(HtmlTextWriterTag.A);
writer.AddAttribute(HtmlTextWriterAttribute.Class, "ms-verticalAlignMiddle");
writer.RenderBeginTag(HtmlTextWriterTag.Span);
writer.Write(name);
writer.RenderEndTag();
}
}
Thanks in advance
Mahdi.
Hi Tobias, is it possible to download this solution?
Hi Gurdip,
I haven't put it out there for download, but all the code is in the blog post here so you should be able to easily patch it together :-)
/ Tob.
Great post, used it to add a photo in top left. Do you have any example on how to add the current site title in the middle of the suit bar? Meaning we could remove it from the titlerow. That would be awesome!
Hi Sind,
I had a similar request from a client recently so I might post an update about that soon. Keep an eye out the coming hours/days.
Tob.
I managed to put the solution together. However, when I deploy, I don't see any changes apart from the Sharepoint text disappearing. I don't have the images you referenced (but I've left the references in), but for the del. control which adds the text hyperlink, even that does not appear? I have a farm-based feature scoped @ the site level, like you have mentioned. This doesn't show up on the central admin (feature activated). What could be wrong?
Works like a dream.. Even for a non VS dude like me :-)
Thank you for sharing Tobias
Hi Jan,
Glad you found it useful :-)
Cheers,
Tob.
I have the same problem as Gurdeep (or even worse) - I cannot even make the SharePoint text disappear. The feature is activated. What am I missing? Should ascx control be registered somewhere on the master page?
If you've done the delegatecontrol feature properly, it should execute. What happens when you debug the code in the user control, does it hit your breakpoint or can you see any content from the actual user control on your page? If not - its not loaded and you need to revise your solution.
If you still can't get it to work, hit up google and search for delegate control in SharePoint 2013 sample code and you'll find plenty of samples on how to build up the artifacts in the project.
Hope this helps.
Tob.
Hy, can you post the code source, thank's
Hi there,
Sorry, you'll have to do that part youself mate.
Cheers,
Tob.
Great, it's done, very interesting post !!
Thank you Sem.
Hi Tobias,
have you used PowerPoint automation services in SP 2013 ? I have correctly configured this one on 3 different VM, but when i run the code to convert ppt file into pdf, i always get this message: the specified document could not be converted....i found nothing in logs'....it seems to be SP 2013 error....
thank you
Has anyone deployed a delegateControl as a feature to the spwebapplication? Trying to make web application feature and from msdn seems to indicate you can do it but VS fails to deploy
Hi Nelson,
Not really - these guys are deployed at the Site or Web scope, where it works wonders.
Cheers,
Tob.
Hello, are you able to use delegate controls with a SharePoint Online Plan?
I implemented this
solution and ran into a problem with the SuiteLinksDelegate.aspx.cs file. The MySuiteLinksUserControl is dependent on
the web application having a connection to a User Profile Service service
application. This makes sense because
the Newsfeed and Sites links are pointing to places in your MySites. If MySites are turned off for your web
application, you’ll see no links at all.
You won’t even see your own, Time Report in this example.
My solution is not to inherit from MySuiteLinksUserControl, but to use UserControl
like normal. I then do what I want in CreateChildControls() and at the end of
your CCC method do a Controls.Add(new MySuiteLinksUserControl()).
Unfortunately, you can't leverage the RenderSuiteLink method any more. However, if your web application isn't
connected to a User Profile Service service application, the Time Report link will
render.
Hi Tobias,
I am having the same problem as some others on here. When I deploy my solution I can see the feature and it is activated, but I do not see my user controls. The SharePoint text disappears, but that is it. If I deactivate the feature, the "SharePoint" text comes back.
When I add a breakpoint to my codebehind file I get the message: Breakpoint will not currently be hit. No symbols have been loaded for this document.
I have followed your example and about 5 other people's examples to the letter and I still can't get anything to work. I have even downloaded sample solutions and they don't work either.
Is there something that I am missing?
Edit: Nevermind! I figured out what was wrong. I was using the Visual Studio 2013 RC, which wasn't working. I switched to 2012 and now everything works as expected... I hope this helps others out there with the same problem.
I never would have thought something like this would break in a new release. Usually it is only minor bugs in new releases. I guess you never know with Microsoft.
Hint for all with problems running this thing: double check
path of ControlSrc in elements.xml – it must correspond to file on disk. I also
used Sequence="1" but I do no think it matters.
I just successfully run it on VS2012 Update 3 & VS2013 (both
with Farm scope).
I tried VS2013 with WebApplication scope and it also works
(I just cannot deploy it with VS2013 to mysites web application – but deployed
on other web apps it works).
Hope this will help anyone.
Greetings
Hi Tobias, in your post you say "SuiteLinksDelegate control will allow us to modify the default links". I simply want to rename SkyDrive to Documents. How should I approach this? Thanks
First let me say thank you Tobias. This helped me tremendously. One of the most well written tutorials. Easy to follow and implement. I had one question, is there any way to edit the items in the dropdown above the "promoted links". Usually it contains the user name, My Site, Log Out, etc. I would like to add a couple links if possible. Thank you again!
Hi Glenn,
Thank you for the kind words, I appreciate it.
Yes you can add more links to that dropdown, the menu is called the user welcome menu and can be altered just like any other custom action: http://sandeepnandey.blogsp...
Enjoy.
Tob.
Hi ,
I am getting following error
Microsoft.SharePoint.Portal.WebControls.LocStringId' does not contain a definition for 'MySuiteLinks_Documents'
What can be done ?
how develop delegates for office 365
Hi Tobias,
Great Tips.....
Help me lot.
Thanks.
Hi Sukanta,
I'm glad you found it useful :-)
Tobias.
very good explanation with example.
its very useful.
thanks a lot tobias
Hi Kingston,
Thank you - appreciate the comment.
Tobias.
hi,
how to this on top link bar
Hi Viki,
Check out my other article here (http://zimmergren.net/techn... and also read the comments for a more complete picture of how it works.
Cheers,
Tobias.
Hello,
Is there any way of doing this with a Script Editor web part?
Hi Yen,
Which part are you referring to? Adding a link?
If you just want to inject links using script you can of course do that with a Script Editor, but instead I'd probably use a ScriptLink from a CustomAction so it'll be persisted on each page and not just one page. In your custom script you can then inject whatever links you want of course.
Tob.
First let me say thank you Tobias, one of the most well written tutorials.
It works perfect on my site but I would like to hide the orignal links "newsfeed, Skydrive..." Is it possible?
Regards
Erik
Hi Erik,
Thank you for your kind comment.
You could hide them with CSS or JavaScript if you prefer, which is what a lot of people have been doing in their environments.
For example: Inject a CustomAction with a ScriptLink to your custom jQuery script, which in turns (on document ready) hides the desired elements from your page source.
Cheers,
Tobias.
Hi Tobias,
Thank you for this useful blog post. I have used SuiteBarBrandingDelegate to show a string which will be different for each release. The problem is that the old string seems have been cached and after each release users need to refresh the page to show the new string. Is there a way to show the new string after each release without refreshing pages?
thanks
Hi Kourosh,
Thank you for the comment.
Refreshing the page seems like something the user would do every now and then either way. But if you have very agile practices and extreme release cadence, I guess you could use an async jquery call to set the text instead, based on the release number which it fetches from somewhere. You could set a timeout for that script so it executes on an intervall.
Personally I wouldn't do it as complex; Refreshing the page happens every now and then with SharePoint anyway. But if there's really a need for it - use a script for hooking it up rather than changing the text in a delegate control, imo.
Hope this helps,
Tobias.
great work,
thanks.
could you check the code for the icon that replaces the "sharepoint" text in the top left corner. it looks like it cant find an img
Ben,
I recently moved the blog from Wordpress to Ghost, and with that some of the code samples and images went broken by the import (sorry).
I will try and fix this during the weekend.
Thanks,
Tobias.
Thanks for your effort and sharing the information
Glad you liked it and thanks for your comment, abdallah!
Cheers,
Tobias.
Hi Tobias, Above Suit bar delegate controls are still valid in SharePoint 2016 on premise?
I am unable to find a link to download this project. Can you refer, please.