There are several ways to create custom applications for the SharePoint platform. Chris Johnson has a great post on this topic with pro and cons of each way.
In this post I will describe how I create "_layouts" application on behalf of the Visual Studio 2005 Web Application Project extension.
- Download and install the Visual Studio 2005 extension "Web Application Project" (… Download, … Documentation).
- In Visual Studio 2005 add a new project of the type "ASP.NET Web Application". Name it appropriate and select as the location the LAYOUTS directory of your SharePoint installation (…12TEMPLATELAYOUTS).
- In the project properties change the output path to the "_app_bin" of your web application
(e.g. "C:InetpubwwwrootwssVirtualDirectories80\_app_bin") - Sign the assembly:
- Add a reference to Windows SharePoint Services in the project.
-
Add a dummy master page to the project with the following content:
<%@
Master
Language="C#"
%>
<!DOCTYPE
html
PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html
xmlns="http://www.w3.org/1999/xhtml"
>
<head
runat="server">
ÿÿÿÿ<title>Untitled Page</title>
</head>
<body>
<form
id="form1"
runat="server">
<div>
ÿÿÿÿ<asp:contentplaceholder
id="PlaceHolderPageImage"
runat="server">
ÿÿÿÿ</asp:contentplaceholder>
</div>
<div>
ÿÿÿÿ<asp:contentplaceholder
id="PlaceHolderPageTitle"
runat="server">
ÿÿÿÿ</asp:contentplaceholder>
</div>
<div>
ÿÿÿÿ<asp:contentplaceholder
id="PlaceHolderPageTitleInTitleArea"
runat="server">
ÿÿÿÿ</asp:contentplaceholder>
</div>
<div>
ÿÿÿÿ<asp:contentplaceholder
id="PlaceHolderMain"
runat="server">
ÿÿÿÿ</asp:contentplaceholder>
</div>
</form>
</body>
</html> -
Add an aspx page (or use Default.aspx) with the following content:
<%@
Page
Language="C#"
AutoEventWireup="true"
CodeBehind="Default.aspx.cs"
MasterPageFile="DummyMasterPage.master"
Inherits="Documena.PDSearch._Default, Documena.PDSearch, Version=1.0.0.0, Culture=neutral, PublicKeyToken=33d7cc1d9943a411"
%><%@
Import
Namespace="Microsoft.SharePoint"
%>
<%@
Import
Namespace="Microsoft.SharePoint.ApplicationPages"
%>
<%@
Register
Tagprefix="SharePoint"
Namespace="Microsoft.SharePoint.WebControls"
Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
%>
<%@
Register
Tagprefix="Utilities"
Namespace="Microsoft.SharePoint.Utilities"
Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
%>
ÿ
<asp:Content
ID="Content1"
contentplaceholderid="PlaceHolderPageTitle"
runat="server">
ÿÿÿÿ<SharePoint:EncodedLiteral
ID="EncodedLiteral1"
runat="server"
text="My Title"
EncodeMethod='HtmlEncode'/>
</asp:Content>
ÿ
<asp:Content
ID="Content2"
contentplaceholderid="PlaceHolderPageTitleInTitleArea"
runat="server">
ÿÿÿÿ<SharePoint:EncodedLiteral
ID="EncodedLiteral2"
runat="server"
text="My Title"
EncodeMethod='HtmlEncode'/>
</asp:Content>
ÿ
<asp:Content
ID="Content3"
contentplaceholderid="PlaceHolderPageImage"
runat="server"/>
ÿ
<asp:Content
ID="Content4"
contentplaceholderid="PlaceHolderMain"
runat="server">
</asp:Content>The point here is the page directive with the MasterPageFile property that references the above created dummy master page and the Inherits property that references the assembly that will be copied to the _app_bin.
-
The corresponding code behind (Default.aspx.cs) looks like:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Utilities;
ÿ
namespace Documena.PDSearch
{
ÿÿÿÿpublic
partial
class
_Default : System.Web.UI.Page
ÿÿÿÿ{
ÿÿÿÿÿÿÿÿprotected
override
void OnPreInit(EventArgs e)
ÿÿÿÿÿÿÿÿ{
ÿÿÿÿÿÿÿÿÿÿÿÿbase.OnPreInit(e);
ÿÿÿÿÿÿÿÿÿÿÿÿusing (SPWeb webCurrent = SPControl.GetContextSite(Context).OpenWeb())
ÿÿÿÿÿÿÿÿÿÿÿÿ{
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿthis.MasterPageFile = webCurrent.MasterUrl;
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ// or: this.MasterPageFile = webCurrent.CustomMasterUrl;
ÿÿÿÿÿÿÿÿÿÿÿÿ}
ÿÿÿÿÿÿÿÿ}
ÿ
ÿÿÿÿÿÿÿÿprotected
void Page_Load(object sender, EventArgs e)
ÿÿÿÿÿÿÿÿ{
ÿ
ÿÿÿÿÿÿÿÿ}
ÿÿÿÿ}
}
ÿ
The point here is the OnPreInit method where we change the master page from our dummy master page to the master page of the current site (SPWeb). (LAYOUTS applications are always called in the context of a site: http://…/sitename/_layouts/MyApp/Default.aspx). - Build the new application within Visual Studio.
-
To run the new application we have to configure it manually in the IIS Manager.
- Start IIS Manager
- Open the Web Sites tree
- Open your SharePoint Web App (e.g. "SharePoint – 80")
- Open "_layouts"
- Select the directory of your application and open the properties dialog
- In the "Directory" tab click on the "Create" button and choose the Application Pool of your SharePoint Web Application
- Click on OK to close the dialog
- Start your Application in the context of a site http://…/sitename/_layouts/MyApp/Default.aspx (You should get an empty page with the master page of the site.)
Drawback of this solution:
Because the assembly is built directly to the _app_bin directory you have to recycle the IIS application pool before rebuilding the application within Visual Studio.
ÿ
Updated 2007-08-24:
Due to the comment of Daniel I did some further investigations. There is indeed a problem if you want to use your layouts Application in the server root web site (e.g. http://server/_layouts/MyApp/Default.aspx). You will get a server error.
ÿ
To avoid this don't configure your directory in the IIS Manager as an application. May be you will get then an empty page (on the server root) or the following message (when you call your application in the context of sub site):
ÿ
ÿ
It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level. This error can be caused by a virtual directory not being configured as an application in IIS. (C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions12 emplatelayoutsMyAppweb.config line 21)
ÿ
ÿ
Correct your web.config (here I had to comment out the line <authentication mode="Windows" /> and everything works fine.