Integrating a Custom ASP.NET Application into SharePoint (Part 2)
Posted by DevExpert on 25th February 2009
In my last post, I began describing how to integrate a custom ASP.NET application into SharePoint. SharePoint is a fantastic platform for building applications, and being able to create your own pages and application structure is a huge win when you need to add missing functionality, or to integrate a non-SharePoint application into SharePoint.
My previous post covered the basics – where to place your custom artifacts, how to inherit the master page and navigation, and how the custom application runs in the context specified in the URL. This post will briefly cover securing your application pages and will also cover some useful design and UI techniques to give your application a truly integrated look and feel.
If you took at a look at the code I provided, you may have noticed that my custom base class that sets the master page is inheriting from LayoutsPageBase. This is a page in the object model that is specifically meant to be inherited, and provides us the means to check the users’ rights. Since Natnael Gebremariam of Bamboo Solutions already did a fantastic job of explaining this and some of the nuances in his post here, I will skip that and just provide a high-level overview. Basically there are 3 properties that can be overridden to customize the required permissions for your page:
- AllowAnonymousAccess: A boolean value indicating if the page is accessible by anonymous users.
- RequireSiteAdministrator: A boolean value indicating if the page is only accessible by site collection administrators.
- RightsRequired: A list of SPBasePermissions that specify the granular permissions that are necessary to access the page.
For the purposes of this blog series I kept it simple, and I’m denying anonymous access, not requiring users to be site collection administrators, but requiring the user to have at least ManageLists and ManageWeb permissions:
protected override bool AllowAnonymousAccess { get { return false; } } protected override bool RequireSiteAdministrator { get { // only allow site collection administrators access? return false; } } protected override SPBasePermissions RightsRequired { get { SPBasePermissions permissions = base.RightsRequired | SPBasePermissions.ManageLists | SPBasePermissions.ManageWeb; return permissions; } }
What I don’t particularly like is only being able to specify the permissions that are available through SharePoint, and not being able to specify my own. What if I wanted to check against Active Directory, or the users’ presence in a group, or validate against a line-of-business application? It’s not built-in, but Natnael describes a pretty good approach that will allow you to accomplish this.
Alright, now that I have the security in place, I can begin building the application. I’m going to pretend this application is a front-end to a line-of-business database that manages my Widget inventory. The focus of the rest of this post is going to be on utilizing some out-of-the-box SharePoint web controls. Don’t pay too much attention to the implementation of these, as this will serve as an overview of some of the server and user controls that you can leverage. In future posts I’ll elaborate a little on some of these and provide the nitty-gritty details, but for the sake of brevity I’ll just be covering the basics here.
First, we need to register the controls that we are going to use at the top of the ASPX pages. This is not a comprehensive list, but should give you the idea:
<%@ Register TagPrefix="wssuc" TagName="InputFormSection" Src="/_controltemplates/InputFormSection.ascx" %> <%@ Register TagPrefix="wssuc" TagName="InputFormControl" Src="/_controltemplates/InputFormControl.ascx" %> <%@ Register TagPrefix="wssuc" TagName="ButtonSection" Src="/_controltemplates/ButtonSection.ascx" %> <%@ Register TagPrefix="wssuc" TagName="ToolBar" Src="/_controltemplates/ToolBar.ascx" %> <%@ Register TagPrefix="wssuc" TagName="ToolBarButton" Src="/_controltemplates/ToolBarButton.ascx" %> <%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
Toolbar/SPToolBarButton
Many applications have a need for a toolbar, and even SharePoint is littered with them. You’re able to build one of your own by using the Toolbar.ascx user control (inside the CONTROLTEMPLATES folder), and the SPToolBarButton controls (found within the Microsoft.SharePoint.WebControls namespace):
<wssuc:Toolbar id="tb" runat="server"> <Template_Buttons> <SharePoint:SPToolBarButton ID="btnAdd" runat="server" Text="Add Widget" ImageUrl="Images/add.gif" NavigateUrl="AddWidget.aspx" /> <SharePoint:SPToolBarButton ID="btnRefresh" runat="server" Text="Refresh List" ImageUrl="Images/refresh1.ico" OnClick="btnRefresh_Click" /> </Template_Buttons> <Template_RightButtons> <SharePoint:SPToolBarButton ID="btnHelp" runat="server" Text="Help" ImageUrl="Images/help.gif" NavigateUrl="Help.aspx" /> </Template_RightButtons> </wssuc:Toolbar>
The above markup will render:
SPGridView
The next control worth mentioning is the all-powerful SPGridView control. This control is inherited from the ASP.NET GridView control which is already a great control, but the SPGridView provides a ton more functionality. In supports grouping, it automatically inherits the styles of SharePoint, and you are able to add drop-down menus to your items, like users are already used to in lists and libraries. The markup syntax is pretty straightforward:
<SharePoint:SPGridView ID="grid" runat="server" AutoGenerateColumns="false" AllowSorting="true" AllowGrouping="true" GroupField="Category" AllowGroupCollapse="true"> <Columns> <asp:BoundField HeaderText="ID" DataField="ID" SortExpression="ID" /> <asp:BoundField HeaderText="Name" DataField="Name" SortExpression="Name" /> <asp:BoundField HeaderText="Price" DataField="Price" SortExpression="Price" /> <asp:BoundField HeaderText="Quantity on Hand" DataField="QuantityOnHand" SortExpression="QuantityOnHand" /> <asp:BoundField HeaderText="Date Added" DataField="DateAdded" SortExpression="DateAdded" /> </Columns> </SharePoint:SPGridView>
The above markup will render
Let’s take this a step further and add the familiar drop-down list to the Name column. There are a ton of examples on how to do this in code-behind, most notably Powlo’s posts here and here, but here’s a little preview on how to do this in the markup. First, we need to create our MenuTemplate, which defines the items in the drop-down list:
<SharePoint:MenuTemplate ID="menuTemplate" runat="server"> <SharePoint:MenuItemTemplate ID="menuEdit" runat="server" Text="Edit Widget" ImageUrl="Images/gear.gif" ClientOnClickScript="javascript:editSomething('%ID%');" /> <SharePoint:MenuItemTemplate ID="menuDelete" runat="server" Text="Delete Widget" ImageUrl="Images/delete.gif" ClientOnClickScript="javascript:deleteSomething('%ID%');" /> </SharePoint:MenuTemplate>
Next, replace the BoundField with an SPMenuField, and specify the menu this is bound to by assigning the MenuTemplateID property to the ID of the menu template we just created. The TokenNameAndValueFields property assigns a token to a field in the data source. In this example, I’m declaring two tokens, one for ID and another for Name, which can then be used elsewhere. The NavigateUrlFields specifies the fields that can be used in the URL set in the NavigateUrlFormat property, and in the same order (it works like the String.Format() method):
<SharePoint:SPMenuField HeaderText="Name" TextFields="Name" MenuTemplateId="menuTemplate" TokenNameAndValueFields="ID=ID,NAME=Name" NavigateUrlFields="ID" NavigateUrlFormat="EditWidget.aspx?id={0}" />
The above markup will render:
Form Fields
For creating form fields, there are a ton of ways to skin this cat, but I typically choose one of the following two approaches. Typically your data-entry forms should either look like the forms used for new list items, or the forms for new lists, sites, or pages. The simplest and arguably cleanest approach is to just use the ASP.NET controls you’re used to, such as a TextBox, DropDownList, etc., and place them in a table that have the SharePoint styles applied to them. The end result will look something like this:
The markup is pretty simple; the important part is is the style classes applied to the elements, specifically ms-formlabel, ms-formbody, and ms-input. For the sake of brevity, here is a portion of the markup for the above form:
<tr> <td class="ms-formlabel"> Date Added: </td> <td class="ms-formbody"> <asp:TextBox id="txtDateAdded" runat="server" CssClass="ms-input" width="200px" /> </td> </tr> <tr> <td class="ms-formlabel"> Category: </td> <td class="ms-formbody"> <asp:DropDownList id="txtCategory" runat="server" CssClass="ms-input" width="200px"> <asp:ListItem>Cheap Widgets</asp:ListItem> <asp:ListItem>Expensive Widgets</asp:ListItem> </asp:DropDownList> </td> </tr>
The second approach is to make the form look like the new list/site pages in SharePoint. This is perfectly fine too, but takes up a little more space:
The markup for this is a little more complex, and involves the use of InputFormSection and InputFormControl sections. A sample of the markup used for the above form is as follows:
<wssuc:InputFormSection runat="server" Title="" id="dateSection"> <template_description> <b>Date</b><br />Please specify a date. </template_description> <template_inputformcontrols> <wssuc:InputFormControl runat="server" LabelText="Date:"> <Template_Control> <wssawc:DateTimeControl ID="txtDate" runat="server" DateOnly="true" /><BR /> </Template_Control> </wssuc:InputFormControl> </template_inputformcontrols> </wssuc:InputFormSection> <wssuc:InputFormSection runat="server" Title="" id="categorySection"> <template_description> <b>Category</b><br />Please specify a category </template_description> <template_inputformcontrols> <wssuc:InputFormControl runat="server" LabelText="Category:"> <Template_Control> <wssawc:InputFormTextBox ID="txtCategory" runat="server" Columns="40" class="ms-input" /><BR /> </Template_Control> </wssuc:InputFormControl> </template_inputformcontrols> </wssuc:InputFormSection> <wssuc:ButtonSection runat="server" ShowStandardCancelButton="false"> <Template_Buttons> <asp:Button runat="server" class="ms-ButtonHeightWidth" Text="Save" id="btnSave" /> <asp:Button runat="server" class="ms-ButtonHeightWidth" Text="Cancel" id="btnCancel" CausesValidation="false" /> </Template_Buttons> </wssuc:ButtonSection>
As you can see, it’s lot more code, but you’re given a few extra things to work with, like the label and label description to the left, and the extra space to the right. You’ll also notice I’m using built-in SharePoint controls for the textboxes and the date picker. There are a bunch of controls that you can leverage, many of which I’ll cover in a future post. If you’re ambitious though, feel free to poke around the assembly with Reflector or the Object Browser in Visual Studio. Here’s a screenshot of what you’ll find:
There’s all kinds of goodies that are available for us to use in our applications. Stay tuned for a future post that will dive into a few more of them!
Tags: .NET, ASP.NET, Object Model, SharePoint, SharePoint UI
Posted in .NET, ASP.NET, Object Model, SharePoint, SharePoint UI | 23 Comments »