Monday, June 9, 2008

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);
}
}

1 comment:

Tom Daly said...

Thanks this was very helpful to me!