Showing posts with label Site Pages. Show all posts
Showing posts with label Site Pages. Show all posts

Monday, June 9, 2008

Designing Site Pages by Using Controls

Custom controls are more lightweight and must be compiled into an assembly DLL before being deployed to the front-end Web server.
Constructing Pages with Custom Controls
developers often choose to create custom controls by deriving from a richer class named WebControl, which inherits from the Control class.
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
namespace CustomSitePages {
public class CustomControl1 : WebControl {
protected override void RenderContents(HtmlTextWriter output) {
SPWeb site = SPContext.Current.Web;
output.Write("Current Site: " + site.Title);
output.Write("
");
output.Write("Current Site ID: " + site.ID.ToString());
} } }
You have two choices as to where to deploy an assembly DLL that contains a custom control when you want to use it in a site page. First, you can compile the assembly DLL with a strong name and install it in the Global Assembly Cache. Alternatively, you can deploy the assembly DLL by placing it inside the root directory of the hosting Web application inside a nested directory named bin. Note that when you plan to deploy the assembly DLL with custom controls in the bin directory, you have the option of compiling it with or without a strong name.Once the assembly DLL with the custom control is properly deployed, you can then reference it within a page template by using the ASP.NET Register directive. The following code example
displays a page template that uses the custom control shown previously.
%@ Page MasterPageFile="~masterurl/default.master"
meta:progid="SharePoint.WebPartPage.Document" %>
%@ Register Assembly="CustomSitePages, ... "
Namespace="CustomSitePages" TagPrefix="CustomSitePages" %>
asp:Content ID="main"
ContentPlaceHolderId="PlaceHolderMain"
runat="server">
h3>A custom control example/h3>
CustomSitePages:CustomControl1 ID="cc1" runat="server" />
/asp:Content>
This TagPrefix value is then used to instantiate instances of the control within the page.
CustomSitePages:CustomControl1 ID="cc1" runat="server" />

When you navigate to .aspx, you should see that the page renders the output of the
control so that it is visible to the user. However, this works only while the hosting page remains in a ghosted state. Remember that customized pages allow only for controls that are registered as safe controls. If a user customizes Page02.aspx with the SharePoint Designer, the page begins to execute in safe mode, and the presence of a control that is not registered as a safe control results in the error message.
To fix this problem, you must add a custom SafeControl entry to the hosting Web
application’s web.config file. You can accomplish this by adding a SafeControl entry that looks like the following:
SafeControl
Assembly="CustomSitePages, ..."
Namespace="CustomSitePages"
TypeName="CustomControl1"
/>
Constructing Pages with User Controls
The ASP.NET runtime provides the functionality to parse these .ascx files at run time and compile them into assembly DLLs just as it does for .aspx files.
Let’s examine the source file for a simple user control. The following example of an .ascx file creates a simple user interface with a command button and a label and adds in an event handler to provide the classic “Hello World” functionality.
%@ Control Language="C#" %>
script runat="server">
protected void cmdButton1_Click(object sender, EventArgs e) {
lblStatus.Text = "Hello, World";
}
/script>
asp:Button ID="cmdAddCustomer" runat="server" Text="Add Customer"
OnClick="cmdAddCustomer_Click" />
br/>
asp:label id="lblStatus" runat="server" text="">
User controls are always loaded from the file system of the front-end Web server and
compiled into assembly DLLs. Furthermore, user controls can be copied to the front-end Web server only by someone with farm-level administrative privileges. For these reasons, you can assume that you can always write in-line code in an .ascx file.
In Chapter 2, you were introduced to the virtual _layouts directory and learned that this was the proper place to deploy application pages. WSS provides a similar virtual directory for deploying user controls. Inside the TEMPLATE directory resides a nested directory named CONTROLTEMPLATES.
Fortunately, you don’t have to worry about this if you deploy your custom user controls inside the virtual _controltemplates directory because the standard web.config file for a Web application already contains the following SafeControl entry:
SafeControl
Src="~/_controltemplates/*"
IncludeSubFolders="True"
Safe="True"
AllowRemoteDesigner="True"
/>
Now that you have seen how to create and properly deploy a user control, the final step is constructing a page template that references the .ascx file and creates an instance. However, the process is different with user controls because the Register
directive requires an src attribute that points to the virtual path of the target .ascx file.
%@ Page MasterPageFile="~masterurl/default.master"
meta:progid="SharePoint.WebPartPage.Document" %>
%@ Register TagPrefix="luc" TagName="UserControl1"
src="~/_controltemplates/Litware/UserControl1.ascx" %>
asp:content runat="server" contentplaceholderid="PlaceHolderMain">
luc:usercontrol1 id="id1" runat="server">
/asp:Content>
Designing Web Part Pages
Web Parts go even further to allow individual users to add personalization changes that are seen only by them.WSS provides the underlying mechanisms to track all of this customization and personalization inside the content database along with all of the other site-related data.
All of the data for tracking Web Part instances and their customization and personalization data are kept in separate tables inside the content database.This means that a Web Part page can remain in a ghosted state even though users are continually adding, customizing, and personalizing the Web Parts within its zone.
To create a Web Part page in an ASP.NET 2.0 application, you must create an .aspx page that contains exactly one instance of a control named WebPartManager and one or more WebPartZone controls. The WebPartManager is responsible for managing the lifetime of Web Part instances as well as serializing Web Part–related data so that they can be stored and retrieved from the tables in the ASP.NET services database.
WSS relies on a specialized control named SPWebPartManager that derives from the ASP.NET 2.0 WebPartManager control. The SPWebPartManager control overrides the standard behavior of the WebPartManager control to persist Web Part data inside the WSS content database instead of inside the ASP.NET services database.
Two things must be done when creating a page template for a Web Part page. The first is to inherit from the WebPartPage class that is defined inside the Microsoft.SharePoint.dll assembly. The second is to add one or more WebPartZone controls.To add WebPartZone controls to a page template, you must add a Register directive that imports all of the controls from the Microsoft.SharePoint.dll assembly defined in the Microsoft.SharePoint.WebPartPages namespace as shown in the following page template definition.
%@ Page Language="C#" MasterPageFile="~masterurl/default.master"
Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage,Microsoft.SharePoint,Version=12.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c"
meta:progid="SharePoint.WebPartPage.Document" %>

%@ Register Tagprefix="WebPartPages"
Namespace="Microsoft.SharePoint.WebPartPages"
Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

asp:content id="main" runat="server" contentplaceholderid="PlaceHolderMain">

h3>Custom Web Part Page/h3>

table width="100%">
tr>
td valign="top" style="width:50%">

/td>
td valign="top" style="width:50%">
WebPartPages:WebPartZone ID="Right" runat="server"
FrameType="TitleBarOnly"
Title="Right Web Part Zone" />
/td>
/tr>
/table>
/asp:Content>


There are two common techniques for adding a Web Part instance to a Web Part zone. The first technique involves a declarative approach used inside a feature in which you define an AllUsersWebPart element inside a File element. The following example demonstrates the File element that is used in the CustomSitePages project to provision the Web Part page named WebPartPage02.aspx.
Elements xmlns="http://schemas.microsoft.com/sharepoint/">
Module Path="PageTemplates" Url="SitePages" >

File Url="WebPartPage.aspx" Name="WebPartPage03.aspx" Type="Ghostable" >

AllUsersWebPart WebPartZoneID="Left" WebPartOrder="0">

Assembly>Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
TypeName>Microsoft.SharePoint.WebPartPages.ContentEditorWebPart
Title>Yet Another Web Part is Born/Title>
FrameType>TitleBarOnly
cewp:Content>
This Web Part was added through declarative logic
/cewp:Content>
/WebPart>
]]>
/AllUsersWebPart>

AllUsersWebPart WebPartZoneID="Right" WebPartOrder="0">

Assembly>Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
TypeName>Microsoft.SharePoint.WebPartPages.ImageWebPart
FrameType>None
Title>Watch My Gears Run/Title>
iwp:ImageLink>/_layouts/images/GEARS_AN.GIF
/WebPart>
]]>
/AllUsersWebPart>
/File>
/Module>
/Elements>
The second technique for adding a Web Part instance to a Web Part page involves writing code against the WSS object model. An example of this type of code is supplied in the FeatureActivated event handler for the CustomSitePages project. The code obtains a reference to the SPFile object associated with WebPartPage03.aspx and uses an SPLimitedWebPart-Manager object to add a new Web Part instance to a particular target zone.
public override void FeatureActivated(
SPFeatureReceiverProperties properties) {
// acquire objects for site, page and limited Web Part Manager
SPWeb site = (SPWeb)properties.Feature.Parent;
SPFile page = site.GetFile("SitePages/WebPartPage03.aspx");
SPLimitedWebPartManager mgr;
mgr = page.GetLimitedWebPartManager(PersonalizationScope.Shared);
// add Web Part to Right Zone
ImageWebPart wp1 = new ImageWebPart();
wp1.ChromeType = PartChromeType.None;
wp1.ImageLink = @"/_layouts/images/IPVW.GIF";
mgr.AddWebPart(wp1, "RightZone", 0);
}
Master Pages
The pages that link to a master page are known as content pages. Standard master page is deployed during the standard WSS installation on the file system of the front-end Web server at the following path (there is a line break in the file path to make it more readable).
C:\Program Files\Common Files\Microsoft Shared
\web server extensions\12\TEMPLATE\GLOBAL\default.master
Whenever you create a new site, WSS provides provisioning instructions to create the Master Page gallery and provision an instance of default.master within the site by using a standard site-relative path.
/_catalogs/masterpage/default.master
The default.master page contains the basic layout for a site page including elements such as HTML, HEAD, BODY, and FORM. Within these standard HTML elements, you will find three important types of components:
■ Controls for links, menus, icons, and navigation components
■ Named placeholders
■ Delegate controls
The top link bar is defined by using a WSS-specific control of type AspMenu along with a SiteMapDataSource control that is configured to point to the standard SPNavigationProvider component. The Quick Launch menu is defined in the same way. The major difference between the two is that the SiteMapDataSource for the top link bar is configured with a StartingNodeUrl attribute with a value of sid:1002, whereas the Quick Launch menu is configured with a StartingNodeUrl attribute with a value of sid:1025.
The next question you should be asking is what the significance is between 1002 and 1025. It has to do with the data stored in the content database for tracking navigation nodes. The top node for the top link bar has an ID of 1002, and the top node to the Quick Launch menu has an ID of 1025.
The CustomSitePages feature provides code in the FeatureActivated event handler to add navigation nodes to construct a custom drop-down menu in a fashion that is not possible to replicate through the user interface. Examine the following code and observe how it creates SPNavigationNode objects and adds them to the collection of nodes that define the structure for the top link bar.
public override void FeatureActivated(SPFeatureReceiverProperties properties) {
// get a hold of current site in context of feature activation
SPWeb site = (SPWeb)properties.Feature.Parent;
SPNavigationNodeCollection topNav = site.Navigation.TopNavigationBar;
// create dropdown menu for custom site pages
SPNavigationNode DropDownMenu1;
DropDownMenu1 = new SPNavigationNode("Site Pages", "", false);
topNav[0].Children.AddAsLast(DropDownMenu1);
// add navigation nodes to create menu items
DropDownMenu1.Children.AddAsLast(
new SPNavigationNode( "Site Page 1",
"SitePages/Page01.aspx"));
DropDownMenu1.Children.AddAsLast(
new SPNavigationNode("Site Page 2",
"SitePages/Page02.aspx"));
}
Delegate Controls
Like a placeholder, a delegate control can optionally supply default content that is used until a substitution is performed.
One major difference when compared to placeholders is that the substitution mechanism for replacing the contents of a delegate control is driven through feature activation. Therefore, you can replace what’s defined inside a delegate control in default.master without requiring any changes to default.master or the site pages that link to it. All you need to do is define a Control element within a feature and then activate that feature.
SmallSearchInputBox delegate control by referencing a built-in user control with the standard WSS search area content.
control
Id="SmallSearchInputBox"
Sequence="100"
ControlSrc="~/_controltemplates/searcharea.ascx"
/>
Assume that you want to get rid of the standard search area content and replace it with your own custom content for a particular business solution. That’s what delegate controls were designed for.
If you want to replace a delegate control, such as the WSS search area, with your own customized version, you start by adding a Control element to a feature. The Control element should have an ID value of SmallSearchInputBox. The Control element should also have a Sequence number smaller than any other active Control element pointing to the same ID. The following code demonstrates how the Control element is defined inside the elements.xml file of the CustomBranding feature.

Note that this Control element has a sequence number of 10, which is smaller than the Control element defined in ContentLightup with a Sequence number of 100. Once the CustomBranding feature is activated within a site collection, all of the site pages that link to default.master replace the standard WSS search area with whatever content you have defined inside the custom user control named LitwareSearchArea.ascx. The following code defines a starting point for creating a custom user control that supplies custom search behavior.
%@ Control Language="C#" %>
script runat="server">
protected void cmdRunSearch_Click(object sender, EventArgs e) {
// add customer search here
txtSearchText.Text = "Hello";
}
/script>

table>
tr>
td>
td>
/tr>
/table>
Creating a Custom Master Page Template
Creating a custom master page template involves several steps. First, you must create the master page template itself. Second, you must create a custom feature that provisions an instance of this master page template inside the Master Page gallery for a specific site. Finally, you need to add some code to redirect site pages to use your custom master page instead of using default.master. The Visual Studio project named CustomBranding provides a working sample that demonstrates how all of the pieces fit together.
You can create a custom template by using two different approaches. First, you can make a copy of default.master and then modify it according to taste. A second approach involves starting from scratch so that you can design the exact HTML layout you’re looking for. The custom master page template used in the CustomBranding project is named Litware.master. The Litware.master template is a variation on the default.master template with changes to allow for fly-out menus on both the top link bar and Quick Launch menu. The CustomBranding feature includes a Module element that has been designed to provision an instance of the Litware.master page template into the Master Page gallery of the top-level site.
Module Name="MasterPages" List="116" Url="_catalogs/masterpage">
File Url="Litware.master" Type="GhostableInLibrary" />
/Module>
However, this Module targets the Master Page gallery, which is a special type of document library. Therefore, the Module is defined with a List attribute of 116, which is the list type identifier for the Master Page gallery. The Url attribute for this Module is defined with a value of _catalogs/masterpage,
which is the standard site-relative path to the Master Page gallery.
We have reviewed the steps involved in creating a master page template and provisioning an instance of it in the Master Page gallery of the top-level site. The next step involves redirecting all site pages within a site to link to this provisioned instance of our custom master page template. To understand the technique for accomplishing this, take a closer look at the MasterPageFile attribute defined within a Page directive. Examine the following page template, which is defined to link to a target master page by using a special syntax in the form of ~masterurl/default.master.
%@ Page MasterPageFile="~masterurl/default.master" %>
asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">
Custom content goes here
/asp:Content>
You can redirect any site page that uses this token by acquiring an SPWeb reference to the current site and then updating the MasterUrl property.
SPWeb site = SPContext.Current.Web;
string MasterUrlPath = site.ServerRelativeUrl;
if (!MasterUrlPath.EndsWith(@"/"))
MasterUrlPath += @"/";
MasterUrlPath += @"_catalogs/masterpage/Litware.master";
site.MasterUrl = MasterUrlPath;
site.Update();
Once you
activate the CustomBranding feature, you can navigate to the application page named
CustomBrand.aspx by using a custom menu item that is added to the Site Settings menu. This application page provides a command button that allows the user to execute the following code.
protected void cmdApplyCustomBrand_Click(object sender, EventArgs e) {
SPWeb site = SPContext.Current.Site.RootWeb
string MasterUrlPath = site.ServerRelativeUrl;
if (!MasterUrlPath.EndsWith(@"/"))
MasterUrlPath += @"/";
MasterUrlPath += @"_catalogs/masterpage/Litware.master";
ApplyCustomBrand(MasterUrlPath, site);
}
protected void ApplyCustomBrand(string MasterUrlPath, SPWeb site) {
site.MasterUrl = MasterUrlPath;
site.Update();
// use recusion to update all child sites in site collection
foreach (SPWeb child in site.Webs) {
ApplyCustomBrand(MasterUrlPath, child);
}
}
The file that defines the majority of the standard CSS classes used by pages in WSS is named core.css.
SPWeb site = SPContext.Current.Web;
site.ApplyTheme("");
site.AlternateCssUrl = "/_layouts/1033/STYLES/Litware/LitwareBrand.css";
site.Update();

Pages and Design

Application pages have an advantage over site pages in that they perform better and provide a developer with the ability to add in-line code. You also learned that site pages have some key advantages over application pages because they can be created dynamically and can also be customized by users on a site-by-site basis.
Page ghosting is an optimization used with site pages in which a single page template can be used to process multiple page instances across many different sites. For example, the home page for every team site in a Microsoft Windows SharePoint Services (WSS) farm is based on an underlying page template named default.aspx that resides on the file system of the front-end Web server. A page template, such as default.aspx, is compiled into an assembly dynamic-link library (DLL) and loaded into memory just once per Web application. However, this page template and its efficient usage of memory can still be used to serve up pages for thousands of sites. This is an obvious advantage toward scalability.

When a user customizes a site page by using the SharePoint Designer and then saves those changes, a customized version of the page definition is stored in the content database. While this provides flexibility from a customization standpoint, it also can have a negative impact on performance and scalability. When the customized page is requested, its page definition must be retrieved from the Backend database server by the SPVirtualPathProvider component and then fed to the ASP.NET compiler, where it is parsed and loaded into memory. You can imagine that a Web application with thousands of customized pages requires more memory
because each customized page definition must be separately parsed and loaded into memory within the application pool that is hosting the current Web application. You should note that customized pages are not processed by using the standard ASP.NET model in which a page is compiled into an assembly DLL. Instead, customized pages are parsed by the ASP.NET page parser(parsing means reading once again…) and then processed using the no-compile mode feature that was introduced with ASP.NET 2.0.
No-compile pages can be loaded into memory and then unloaded in a manner that is not
possible for compiled pages because the .NET Framework doesn’t really support the concept of unloading an assembly DLL from memory. The closest equivalent would be to recycle the current Windows process or the current .NET AppDomain. However, this type of recycling involves unloading all assembly DLLs from memory, not just those assembly DLLs that haven’t been used recently. Furthermore, the .NET Framework places an upper limit on the number of assembly DLLs that can be loaded into a .NET AppDomain.
No-compile pages provide higher levels of scalability because they do not require loading new assembly DLLs or managed classes into memory. Instead, the processing of no-compile pages involves loading control trees into memory. WSS can manage the memory usage for the control trees associated with customized pages more efficiently because they are not compiled into assembly DLLs. For example, once WSS has finished processing a customized page, it can unload the page’s control tree to free up memory for other purposes. Furthermore, nocompile pages eliminate the need to go through the compilation process, which actually provides faster response times for pages upon first access.
In ASP.NET2.0 dynamic compilation means –asp.net parser take .aspx &.cs file then parse and compiled it.There is no dll files.

Programming with SPFile Objects
WSS tracks each site page as a file within the content database. You can access a site page through the WSS object model by using the SPFile object. For example, assume that you want to program against the home page for a site. You can obtain a reference to the required SPFile object by using the GetFile method of a SPWeb object.
SPWeb site = SPContext.Current.Web;
SPFile homePage = site.GetFile("default.aspx");
The SPFile class makes it possible to read and write to the contents of a site page. For example,the OpenBinary method of an SPFile object returns a binary array containing the page contents. The OpenBinaryStream method returns a System.IO.Stream object. Each of these methods provides an approach for reading the contents of a site page. An SPFile object also provides a SaveBinary method that allows you to update the contents of a site page as well.Note that updating the contents of a site page by using this method customizes the page and moves it into an customized or unghosted state.
Tip Ghosted and uncustomized are terms used to describe site pages served up using file system templates. Unghosted and customized both refer to pages that exist entirely in the database, which no longer depend on a file system template.
// write out new page in memory stream
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.WriteLine("");
writer.WriteLine("Hello, World");
writer.WriteLine("");
writer.Flush();
// add new page to site
SPWeb site = SPContext.Current.Web;
site.Files.Add("hello.htm", stream);
The SPFile class provides a CustomizedPageStatus property that makes it possible to determine whether a site page has been customized and placed in an unghosted state. The SPFile object also provides a method named RevertContentStream that removes any customizations and returns an unghosted page to its initial ghosted state.

SPFolder Objects
Each SPFolder object contains a Files property that allows you to enumerate through its files. If you want to enumerate through all of the files at the root folder of a site, you can access the RootFolder property of a SPWeb object and then use a foreach loop to enumerate through all of its files.
SPWeb site = SPContext.Current.Web;
SPFolder rootFolder = site.RootFolder;
foreach (SPFile file in rootFolder.Files){
// process each file
}
The following code displays an example of custom
code that starts at the root folder of a site and uses recursion to populate an ASP.NET
TreeView control.
const string SITE_IMG = @"\_layouts\images\FPWEB16.GIF";
const string FOLDER_IMG = @"\_layouts\images\FOLDER16.GIF";
const string GHOSTED_FILE_IMG = @"\_layouts\images\NEWDOC.GIF";
const string UNGHOSTED_FILE_IMG = @"\_layouts\images\RAT16.GIF";
protected override void OnLoad(EventArgs e) {
SPWeb site = SPContext.Current.Web;
SPFolder rootFolder = site.RootFolder;
TreeNode rootNode = new TreeNode(site.Url, site.Url, SITE_IMG);
LoadFolderNodes(rootFolder, rootNode);
treeSiteFiles.Nodes.Add(rootNode);
treeSiteFiles.ExpandDepth = 1;
}
protected void LoadFolderNodes(SPFolder folder, TreeNode folderNode) {
foreach (SPFolder childFolder in folder.SubFolders) {
TreeNode childFolderNode = new TreeNode(childFolder.Name,
childFolder.Name,
FOLDER_IMG);
LoadFolderNodes(childFolder, childFolderNode);
folderNode.ChildNodes.Add(childFolderNode);
}
foreach (SPFile file in folder.Files) {
TreeNode fileNode;
if (file.CustomizedPageStatus == SPCustomizedPageStatus.Uncustomized) {
fileNode = new TreeNode(file.Name, file.Name, GHOSTED_FILE_IMG);
}
else {
fileNode = new TreeNode(file.Name, file.Name, UNGHOSTED_FILE_IMG);
}
folderNode.ChildNodes.Add(fileNode);
}
}

Site Pages versus Application Pages

Pages that support user customization are known as site pages. Every one of these site pages would become unghosted. This would negatively impact scalability by forcing the front-end Web server to retrieve each page separately from the content database. Each page would also have to be individually parsed and loaded into memory.

There is only one version of an application page scoped at the farm level, it can be
compiled into a single DLL and loaded into memory once for each Web application. You
never have to worry about the existence of different versions of an application page for different sites. Furthermore, application pages are not subject to attack from users who have permissions to customize site pages. Therefore, WSS does not prohibit them from containing in-line code.
There is only one version of an application page scoped at the farm level, it can be
compiled into a single DLL and loaded into memory once for each Web application.
Let us now summarize the difference between site pages and application pages. Site pages support page customization. Examples of site pages include the home page (default.aspx) for a site as well as the pages associated with lists and document libraries, such as AllItems.aspx, NewForm.aspx, and EditForm.aspx. The fact that site pages support customization provides flexibility but can also impact performance and scalability.Application pages do not support customization, which gives them two distinct advantages over site pages. First, each application page is always compiled into a single DLL so that it performs and scales better than a site page. Second, application pages are allowed to have in-line code.
Creating Custom Application Pages
As a rule, application pages should derive from a base class in the Microsoft.SharePoint assembly named LayoutsPageBase.

ApplicationPage1.aspx
%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" % >
%@ Assembly Name="CustomApplicationPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d4e5777b16a5749f" % >

%@ Page Language="C#" MasterPageFile="~/_layouts/application.master"
Inherits="CustomApplicationPages.ApplicationPage1"
EnableViewState="false" EnableViewStateMac="false" %>

asp:content id="Main" contentplaceholderid="PlaceHolderMain" runat="server">
table border="1" cellpadding="4" cellspacing="0" style="font-size:12">
tr>
td>Site Title:
td>
/tr>
tr>
td>Site ID:
td>
/tr>
/table>
/asp:Content>
asp:Content ID="PageTitle" runat="server"
contentplaceholderid="PlaceHolderPageTitle" >
Hello World
/asp:Content>
asp:Content ID="PageTitleInTitleArea" runat="server"
contentplaceholderid="PlaceHolderPageTitleInTitleArea" >
Application Page 1: 'Hello World' with code behind
/asp:Content>
ApplicationPage1.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace CustomApplicationPages {

public class ApplicationPage1 : LayoutsPageBase {

// add control fields to match controls tags on .aspx page
protected Label lblSiteTitle;
protected Label lblSiteID;

protected override void OnLoad(EventArgs e) {

// get current site and web
SPSite siteCollection = this.Site;
SPWeb site = this.Web;

// program against controls on .aspx page
lblSiteTitle.Text = site.Title;
lblSiteID.Text = site.ID.ToString().ToUpper();
}

}
}
Creating an Application Page with the SPGridView Control
You can see that the class named ApplicationPage2 works together with a custom helper class named PropertyCollectionBinder to create an ADO.NET DataTable object filled with information about the current site and site collection. The DataTable object is being used in this example because its contents can be used to populate SPGridView by using standard ASP.NET data binding techniques.
protected override void OnLoad(EventArgs e)
{
SPSite siteCollection = this.Site;
SPWeb site = this.Web;
// PropertyCollectionBinder pcb = new PropertyCollectionBinder();
PropertyCollectionBinder pcb = new PropertyCollectionBinder();
pcb.AddProperty("Site Title", site.Title);
pcb.AddProperty("Site ID", site.ID.ToString().ToUpper());
pcb.AddProperty("Site Master Page Url", site.MasterUrl);
pcb.AddProperty("Site URL", site.Url);
pcb.AddProperty("Site Collection URL", siteCollection.Url);
pcb.AddProperty("Site Collection ID", siteCollection.ID.ToString().ToUpper());
pcb.AddProperty("Current User Name", site.CurrentUser.Name);
pcb.AddProperty("Is User Site Collection Admin", site.UserIsSiteAdmin.ToString());
pcb.AddProperty("Is User Site Admin", site.UserIsWebAdmin.ToString());
pcb.AddProperty("Site User Count", site.SiteUsers.Count.ToString());
pcb.AddProperty("Host Name", siteCollection.HostName);
pcb.AddProperty("Zone", siteCollection.Zone.ToString());
pcb.AddProperty("Site Collection System Account", siteCollection.SystemAccount.Name);
pcb.BindGrid(grdPropertyValues);
}
%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
%@ Assembly Name="CustomApplicationPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d4e5777b16a5749f" %>

%@ Page Language="C#" MasterPageFile="~/_layouts/application.master"
Inherits="CustomApplicationPages.ApplicationPage2"
EnableViewState="false" EnableViewStateMac="false" %>

%@ Register Tagprefix="SharePoint"
Namespace="Microsoft.SharePoint.WebControls"
Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

asp:content id="Main" contentplaceholderid="PlaceHolderMain" runat="server">

SharePoint:SPGridView runat="server"
ID="grdPropertyValues"
AutoGenerateColumns="false"
RowStyle-BackColor="#DDDDDD"
AlternatingRowStyle-BackColor="#EEEEEE" />

/asp:Content>
PropertyCollectionBinder.cs
{

protected DataTable PropertyCollection = new DataTable();

public PropertyCollectionBinder() {
PropertyCollection.Columns.Add("PropertyName", typeof(string));
PropertyCollection.Columns.Add("PropertyValue", typeof(string));
}

public void AddProperty(string PropertyName, string PropertyValue) {
DataRow newRow = PropertyCollection.Rows.Add();
newRow["PropertyName"] = PropertyName;
newRow["PropertyValue"] = PropertyValue;
}

public void BindGrid(SPGridView grid) {

SPBoundField fldPropertyName = new SPBoundField();
fldPropertyName.HeaderText = "Property Name";
fldPropertyName.DataField = "PropertyName";
grid.Columns.Add(fldPropertyName);

SPBoundField fldPropertyValue = new SPBoundField();
fldPropertyValue.HeaderText = "Value";
fldPropertyValue.DataField = "PropertyValue";
grid.Columns.Add(fldPropertyValue);

grid.Width = new Unit(400);

grid.AutoGenerateColumns = false;
grid.DataSource = PropertyCollection.DefaultView;
grid.DataBind();


}
}
Restricting Application Pages to Site Administrators
Application pages are often designed to provide information and functionality
that should only be accessible to site administrators.
Let’s start by revisiting the creation of a CustomAction element within a feature. You can add an attribute named RequireSiteAdministrator and assign it a value of true so that the menu item only displays to those users who are also site administrators.
RequireSiteAdministrator="True"
While this provides a good start by hiding the menu item from users who are not site
administrators, it doesn’t provide a truly secure solution. The application page itself will still be accessible to any user who knows the URL. When you want to lock down an application page in a secure manner, you can accomplish this by overriding the RequireSiteAdministrator property of the LayoutsPageBase base class as shown in the following code.
public class ApplicationPage3 : LayoutsPageBase {
protected override bool RequireSiteAdministrator {
get { return true; }
}
protected override void OnLoad(EventArgs e) {
// your code goes here
} }
{
// get current site and web
SPSite siteCollection = this.Site;
SPWeb site = this.Web;

lblSiteTitle.Text = site.Title;
lblSiteUrl.Text = site.Url.ToLower();
lblSiteCollectionUrl.Text = siteCollection.Url.ToLower();
lstLists.Items.Clear();
foreach (SPList list in site.Lists) {
lstLists.Items.Add(list.Title);
}
lstLists.Rows = lstLists.Items.Count;
lstSiteUsers.Items.Clear();
foreach (SPUser user in site.SiteUsers) {
lstSiteUsers.Items.Add(user.Name);
}
lstSiteUsers.Rows = lstSiteUsers.Items.Count;

}
Adding a Custom Menu Item to the ECB (EditControlBlock)Menu

CustomAction Id="CustomApplicationPage4"
RegistrationType="List"
RegistrationId="101"
ImageUrl="/_layouts/images/GORTL.GIF"
Location="EditControlBlock"
Sequence="240"
Title="Application Page 4" >
urlaction url="~site/_layouts/CustomApplicationPages/ApplicationPage4.aspx?ItemId={ItemId}&ListId={ListId}">
/customaction>
Note that 101 is a list type identifier that applies to all document libraries. WSS dynamically replaces the {ListId} token with the identifying GUID for the current list or document library.
WSS dynamically replaces the {ItemId} token with the integer identifier for the current list item or document.
You can assume that you are dealing with a document library and not simply a standard list type. In these situations, you can add code that converts the SPList object into a SPDocumentLibrary object. You can also access the document in question directly by creating an SPFile object as shown in the following sample.
{

// get current site and web
SPSite siteCollection = this.Site;
SPWeb site = this.Web;

lblSiteTitle.Text = site.Title;
lblSiteUrl.Text = site.Url.ToLower();
string ListId = Request.QueryString["ListId"];
lblListID.Text = ListId;
SPList list = site.Lists[new Guid(ListId)];
lblListTile.Text = list.Title;
lblRootFolderUrl.Text = list.RootFolder.Url;
string ItemId = Request.QueryString["ItemId"];
lblDocumentID.Text = ItemId;
SPListItem item = list.Items.GetItemById(Convert.ToInt32(ItemId));
lblDocumentName.Text = item.Name;
lblDocumentUrl.Text = item.Url;

if (list is SPDocumentLibrary) {
SPDocumentLibrary documentLibrary = (SPDocumentLibrary)list;
lblDocumentTemplateUrl.Text = documentLibrary.DocumentTemplateUrl;

SPFile file = site.GetFile(item.Url);
lblFileAuthor.Text = file.Author.Name;
lblFileSize.Text = file.TotalLength.ToString("0,###") + " bits";
lblFileLastModified.Text = "By " + file.ModifiedBy.Name +
" on " + file.TimeLastModified.ToLocalTime().ToString();
lblFileCheckOutStatus.Text = file.CheckOutStatus.ToString();
}
}
Imp Points
1-If in IIS website has 10 ASP.NET app u have to create explicitly 10 virtual directories.But in WebApp u no need to go Mgr to create Virtual Dir.It is a single process for creaing n no of SiteCollections.
2-For each Asp.net APP u have to maintain 1 web.config.But in MOSS only one web.config for a WEB APP.In this u can maintain n no of site collections.