Integrating a Custom ASP.NET Application into SharePoint (Part 3)
Posted by DevExpert on March 4th, 2009
In my last two posts here and here I began describing how to integrate a custom ASP.NET application into SharePoint. The first post focused on the essentials, and detailed how to get your application into the SharePoint LAYOUTS folder structure, specifically where to place your files and how to inherit SharePoint’s look and feel by using its master page. The second post focused on configuring permissions for your application and also demonstrated a few handy built-in controls that you can leverage to give your application that true SharePoint-like integrated look and feel.
This post will explain how to add custom navigation for your application. There are a few different approaches that I like to take depending on the application, and I’ll demonstrate a couple of them for you. These can be used in any combination in order to achieve the navigation you’re aiming for. In fact, I recommend a combination of these to achieve a fully integrated navigation structure.
Approach #1: Quick Launch Navigation
Now, modifying the Quick Launch navigation menu is a trivial task. Simply go to Site Actions > Site Settings and find the settings to modify the navigation (Quick Launch on team sites, and Navigation on publishing sites), and add and remove nodes to your heart’s content. While this manual method works just fine, it’s just that: manual. I always have the mindset of if I’m already deploying an application somewhere, I might as well automate as much of the setup steps as I can. Luckily through the use of features we are able to accomplish this easily.
For the sake of brevity, I am going to assume you know what a SharePoint feature is, what a solution package is, and how to create and deploy them. If not, there are plenty of great resources out there that will help you out. Anyways, the first step is to create the feature and associated feature receiver that will execute when the feature is activated on the site. The feature receiver is going to utilized the SharePoint Object Model to create navigation items.
The first step is to create the feature receiver, which must inherit from the SPFeatureReceiver class and must implement the standard 4 feature operations: FeatureActivated, FeatureDeactivated, FeatureInstalled, and FeatureUninstalled. For this post I’m only adding the items in the FeatureActivated event, but it’s probably a good idea to clean these up in the FeatureDeactivated event in case the feature is ever deactivated. My feature receiver looks like this:
namespace DevExpertise.LayoutsApp { public class FeatureReceiver: SPFeatureReceiver { public override void FeatureActivated(SPFeatureReceiverProperties properties) { using (SPWeb site = (properties.Feature.Parent as SPWeb)) { // create the nodes SPNavigationNode widgetManagementNode = new SPNavigationNode("Widget Management", SPUrlUtility.CombineUrl(site.Url, "DevExpertise.LayoutsApp/WidgetMgmt.aspx"), true); SPNavigationNode viewWidgetsNode = new SPNavigationNode("View Widgets", SPUrlUtility.CombineUrl(site.Url, "DevExpertise.LayoutsApp/WidgetList.aspx"), true); SPNavigationNode addWidgetNode = new SPNavigationNode("Add Widget", SPUrlUtility.CombineUrl(site.Url, "DevExpertise.LayoutsApp/AddWidget.aspx"), true); SPNavigationNode widgetSettingsNode = new SPNavigationNode("Modify Widget Settings", SPUrlUtility.CombineUrl(site.Url, "DevExpertise.LayoutsApp/WidgetSettings.aspx"), true); // add the Widget management node to the menu (must be done first) site.Navigation.QuickLaunch.AddAsLast(widgetManagementNode); // add the sub-items to the Widget Management node widgetManagementNode.Children.AddAsLast(viewWidgetsNode); widgetManagementNode.Children.AddAsLast(addWidgetNode); widgetManagementNode.Children.AddAsLast(widgetSettingsNode); // update the site site.Update(); } } public override void FeatureDeactivating(SPFeatureReceiverProperties properties) { // do nothing } public override void FeatureInstalled(SPFeatureReceiverProperties properties) { // do nothing } public override void FeatureUninstalling(SPFeatureReceiverProperties properties) { // do nothing } } }
As you can see, it’s not complicated at all. Simply add as many SPNavigationNodes as you like! The next step is to tell the feature to execute the custom feature receiver. For that just add the ReceiverAssembly and ReceiverClass elements to your feature definition file:
<?xml version="1.0" encoding="utf-8"?> <Feature Id="5856617E-BED2-4705-B030-735F7483225E" Title="DevExpertise Layouts Application" Description="Contains the necessary components for the DevExpertise custom LAYOUTS application." Version="1.0.0.0" Scope="Web" Hidden="false" ImageUrl="DevExpertise\devexpertiseLogo.png" ReceiverAssembly="DevExpertise.LayoutsApp, Version=1.0.0.0, culture=neutral, PublicKeyToken=d39eedb6cff9b1c8" ReceiverClass="DevExpertise.LayoutsApp.FeatureReceiver" xmlns="http://schemas.microsoft.com/sharepoint/"> </Feature>
Once the feature is properly installed, it will show up under Site Features (note that this is scoped at the site level, and will need to be activated on each site):
Cross your fingers, activate it, and you should the new navigation items:
Not too shabby for a few lines of code, huh? You’re just as able to add items to the top navigation if you so desire too.
Approach #2: Custom Actions
One of my favorite things about SharePoint is the ability to extend just about anything, making it a true application development. Menu items are no exception, and they’re painfully simple to implement. You are able to add a custom link to the Site Actions menu, Site Settings menus, list menus, individual item menus, Central Administration menus, etc. If SharePoint has a menu somewhere, chances are you’re able to add your own item to it. There are 2 ways to do this and I’ll only be demonstrating it one way. In a future blog post I’ll show how to do all this stuff programmatically for an even more robust navigation structure.
For this sample Widgets application, I would like to take the navigation a bit further and add an item to the Site Actions menu and also create a group in Site Settings that will allow me to manage my application. To accomplish this, I added a new element manifest to my feature called CustomActions.xml, which will define our custom actions. Per MSDN, custom action files are included as part of a feature and deployed as XML element descriptions, and structured with a CustomAction element, which serves as the core definition for a single action of a link or toolbar item. The following is my CustomActions.xml file, which defines a single action for the Site Actions menu:
<?xml version="1.0" encoding="utf-8" ?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <CustomAction Id="ManageWidgetAction" GroupId="SiteActions" Location="Microsoft.SharePoint.StandardMenu" Sequence="1" Title="Manage Widgets" Description="Manage your company's widget catalog." ImageUrl ="/_layouts/images/actionssettings.gif" Rights="ManageWeb,ManageLists"> <UrlAction Url="~site/_layouts/DevExpertise.LayoutsApp/ManageWidgets.aspx" /> </CustomAction> </Elements>
Let’s break this down a little bit:
- Id. The ID of your custom action.
- GroupId. A pre-defined or custom that determines what group it will be placed into. A comprehensive list of built-in values can be found here.
- Location. The location at which your custom action will be applied. A comprehensive list of built-in values can be found here.
- Sequence. The order in which your custom action will appear in relation to other custom actions.
- Title. The display title of the action.
- Description. The description of the action, if applicable.
- ImageUrl. The image that is displayed next to the action, if applicable.
- Rights. A comma delimited list of SPBasePermission enumeration items. A comprehensive list of values can be found here.
- RequireSiteAdministrator. A true/false value indicating if this option is only visible to the site collection administrator.
- UrlAction: This element defines where the link will take you. Be sure to specify either the ~site or ~sitecollection token which tells SharePoint to build the URL relative to either the site or site collection, respectively.
Simply modify the feature to include this element manifest, redeploy it, reactivate it, and you should see the following in your Site Actions menu:
Easy, huh? Let’s take this a step further and add a few items to the Site Setting page. You can either add items to existing groups on that page, or create your own. I created my own by specifying CustomActionGroup in my CustomActions.xml file, as well as a few CustomAction elements that will be a part of my custom group. The XML is fairly straightforward:
<CustomActionGroup Id="LayoutsAppCustomActionGroup" Title="Widget Application Settings" Sequence="1" Location="Microsoft.SharePoint.SiteSettings"> </CustomActionGroup> <CustomAction Id="UserGroupAdminLinkForSettings" GroupId="LayoutsAppCustomActionGroup" Location="Microsoft.SharePoint.SiteSettings" Rights="ManageWeb,ManageLists" Sequence="1" Title="Manage Widget Categories"> <UrlAction Url="~site/_layouts/DevExpertise.LayoutsApp/Categories.aspx" /> </CustomAction> <CustomAction Id="UserGroupAdminLinkForSettings" GroupId="LayoutsAppCustomActionGroup" Location="Microsoft.SharePoint.SiteSettings" RequireSiteAdministrator="TRUE" Sequence="2" Title="Modify Widget Permissions"> <UrlAction Url="~site/_layouts/DevExpertise.LayoutsApp/Permissions.aspx" /> </CustomAction>
The only notable thing to point out here is for the CustomAction elements, the GroupId is that of the CustomActionGroup I specified first. This tells SharePoint to put these actions in the custom group. Redeploy and reactivate your feature, and you will now have this in your Site Settings page:
Hopefully you can see from this post that it’s pretty easy to build navigation for your custom application and have that created when your application is deployed via a custom feature. In the next and final post in this series, I will show my approach to packaging everything up into features and solution packages, and how to deploy that to SharePoint in a simple and streamlined fashion. Stay tuned!
March 26th, 2009 at 3:32 pm
Do you have this “approach to packaging everything up into features and solution packages, and how to deploy that to SharePoint in a simple and streamlined fashion”?
March 30th, 2009 at 12:29 pm
Are you still planning to do this …
“approach to packaging everything up into features and solution packages, and how to deploy that to SharePoint in a simple and streamlined fashion”
It helps lot of people like me … PLEASE
March 30th, 2009 at 11:44 pm
Are you gonna do this …
“approach to packaging everything up into features and solution packages, and how to deploy that to SharePoint in a simple and streamlined fashion”
PLEASE PLEASE PLEASE PLEASE PLEASE PLEASE
April 2nd, 2009 at 5:12 am
Excellent tutorial! Thanks for spending time to clarify this to the SharePoint community!
April 13th, 2009 at 5:56 pm
Great posts! Are you going to do the final installment soon? It would be greatly appreciated. Plus, can you PLEASE post the source code?! That would be fantastic!
thanks and great job.
April 14th, 2009 at 1:03 pm
Thanks! I actually posted the final installment a couple weeks ago, which can be viewed here.
I’m not planning on posting the source code, because it’s pretty incomplete for these posts, and the source code wouldn’t “just work”. I posted all code I worked with though, so there’s not something you’d be missing by not having all of it.
May 18th, 2009 at 3:42 pm
How can I download the code?
July 31st, 2009 at 3:59 pm
Nice, very nice (blogs)!!! Your blog series on this helped me tremendously in integrating my asp.net web app to wss 3.0. It was a great starting point. Mahalo Nui Loa (Thank you very much)! Aloha!
November 10th, 2009 at 11:39 am
Do you know a source I can use to create my navigation treeview and replace SP quick launch navigation bar?
Great job and thanks for showing us the way.
Mohamed
November 10th, 2009 at 11:40 am
Sorry I missed to add tha tthe treeview will be populated from a database source.
Thanks again.
Mohamed