Sunday, October 23, 2011

Creating Custom Site Pages SharePoint 2007

There's so many SharePoint things I want to blog about but, I'm having a hard time writing posts that aren't long and rambling with multiple topics. You'll be amused to know that drafting this post took me more than ten days... anyways.. let's get started....

It is a general concept that we cannot create custom site pages without out of the box approaches and SPD. However, very infrequently it becomes a requirement to get a site page propagated. This post is dedicated to handle such a kind of situation.  As I progress thru the article, will reveal some tricks to implement a site page created in visual studio.

Before proceeding further, let me give you a glimpse of the solution I created.

clip_image002

 

The important components are:

1.       Page feature

2.       The page called “Default.aspx”

3.       Feature Receiver code (this feature code is required if at all we want to add any web part into the page)

 

The page –Default .aspx , is very interesting here.. let us start digging here.  If we create a blank web part page and download the same from the pages library and open it in the visual studio we would get the same aspx code.  I did the same thing to support the required page references. One thing  I forgot to mention is that the site should be a publishing site, although it is obvious without that the pages library would not make any sense. 

Now let us see the  aspx code would looks like

<%@ Page Inherits="Microsoft.SharePoint.Publishing.TemplateRedirectionPage, Microsoft.SharePoint.Publishing,Version=12.0.0.0,Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

 

<%@ Reference VirtualPath="~TemplatePageUrl" %>

<%@ Reference VirtualPath="~masterurl/custom.master" %>

<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882">

<head>

    <!--[if gte mso 9]><xml>

<mso:CustomDocumentProperties>

<mso:PublishingContact msdt:dt="string"></mso:PublishingContact>

<mso:display_urn_x003a_schemas-microsoft-com_x003a_office_x003a_office_x0023_PublishingContact msdt:dt="string">System Account</mso:display_urn_x003a_schemas-microsoft-com_x003a_office_x003a_office_x0023_PublishingContact>

<mso:PublishingContactPicture msdt:dt="string"></mso:PublishingContactPicture>

<mso:PublishingContactName msdt:dt="string"></mso:PublishingContactName>

<mso:Comments msdt:dt="string"></mso:Comments>

<mso:PublishingContactEmail msdt:dt="string"></mso:PublishingContactEmail>

<mso:ContentType msdt:dt="string">Welcome Page</mso:ContentType>

</mso:CustomDocumentProperties>

</xml><![endif]-->

    <title>My Project(s)</title>

</head>

 

In first instance this code does not make any sense, however, this piece of code is required for any site page to run.  If you download any page from the Page library and open it in the Visual Studio, you will get the same piece of code.

 

Next let me show the feature and its corresponding elements.xml file. While going thru the elements.xml see the tricks to push the page in pages library.

Feature file

<?xml version="1.0" encoding="utf-8"?>

<Feature  Id="0EB6xxxx-3xxD-4xxx-9061-4xxxxxxxxxx9"

          Title="PP.My Projects Site Page"

          Description="Installs My Porject Landing Page in Pages Library"

          Version="1.0.0.0"

          Hidden="FALSE"

          Scope="Web"

          DefaultResourceFile="core"

          ImageUrl="menuprofile.gif"

          ReceiverAssembly="MySPCustomSitePages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7e1xxxxxxxx"     ReceiverClass="MySPCustomSitePages.FeatureReceiverCode.MySPCustomSitePageFR"

          xmlns="http://schemas.microsoft.com/sharepoint/" >

  <ElementManifests>

    <ElementManifest Location="Elements.xml"/>

    <ElementFile Location="pages/Default.aspx"/>

  </ElementManifests>

</Feature>

 

The corresponding elements file

<?xml version="1.0" encoding="utf-8" ?>

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

  <Module Name="MyProjects" Url="Pages" Path="Pages">

    <File Url="default.aspx" Name="MyProjectsLanding.aspx" Type="GhostableInLibrary" >

      <Property Name="Title" Value="My Projects" />

      <Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/BlankWebPartPage.aspx, Blank Web Part Page" />

      <Property Name="ContentType" Value="Welcome Page" />

    </File>

  </Module>

</Elements>

 

Now it is time to explore the feature receiver class which does all the hard work to push web parts into the page in the pages library. If you do not have the requirement of adding web parts or navigation etc., then you can skip this class file. The all the magic is done by the elements.xml. The Module –> File is the place where the page is getting inserted.

public override void FeatureActivated(SPFeatureReceiverProperties properties)

        {

            SPWeb oWeb = properties.Feature.Parent as SPWeb;

            CreatePageElements(oWeb);

        }

        #region Create Page Elements

        public static void CreatePageElements(SPWeb oWeb)

        {

            SPFile webPartPage;

            try

            {

                ////Get the Page from Pages Library - for name of the page see elements.xml

                webPartPage = oWeb.GetFile("pages/MyProjectsLanding.aspx");

                if (webPartPage.CheckOutStatus == SPFile.SPCheckOutStatus.None)

                {

                    ////check ou the page for edit

                    webPartPage.CheckOut();

                }

                else

                {

     ////if already checked out then undo checkout and then checkout again

                    webPartPage.UndoCheckOut();

                    webPartPage.CheckOut();

                }

            }

            catch (ArgumentException ex)

            {

                LogException(ex);

                return;

            }

            try

            {

                using (SPLimitedWebPartManager webpartManager = webPartPage.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared))

                {

                    ////Add Custom Web Part -

                    //DMSActiveBugs wpd = new DMSActiveBugs();

                    //wpd.Title = "Active Bugs";

                    //webpartManager.AddWebPart(wpd, "TopLeftRow", 1);

                    // Check in the default page

                    webPartPage.CheckIn("Added Webparts", SPCheckinType.MajorCheckIn);

                    webPartPage.Update();

                    if (webpartManager.Web != null)

                    {

                        webpartManager.Web.Dispose();

                    }

                }

            }

            catch (Exception ex)

            {

                LogException(ex);

            }

            //AddToNavigationTab(web);

        }

        #endregion

 

private static void AddToNavigationTab(SPWeb web)

        {

            SPNavigationNodeCollection navigation = web.Navigation.TopNavigationBar;

            SPNavigationNode oDMSNode = new SPNavigationNode("Defect Management", web.ServerRelativeUrl + "/pages/MyProjectsLanding.aspx", true);

            navigation[navigation.Count - 1].Children.AddAsFirst(oDMSNode);

        }

 

        #region Feature Deactivating

       

/// Method invoked when feature is deactivated        [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)

        {

            SPWeb web = properties.Feature.Parent as SPWeb;

            SPFile webPartPage = web.GetFile("pages/MyProjectsLanding.aspx");

            webPartPage.Delete();

        }

        #endregion

 

 

Now  build and deploy to see the magic happening yourself.... J

Thanks for reading. If you have some other explanation – please post a comment… I’ll be happy to hear.

...HaPpY CoDiNg

Partha (Aurum)

 

If you have successfully deployed and got the desired result then for some theory knowledge you can read further, you can find this in numerous places too, I kept it here just for my reference, you may skip this as well.

Application Pages

Application Pages are non customizable and are found in the C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS, its worthy to note that this physical directory is mapped to the virtual _layouts directory whenever WSS/MOSS creates a new Web application in the IIS. By using this mapping scheme along with some additional processing logic, the WSS/MOSS runtime can make each application page accessible within the context of any site in the farm.

When building custom application pages you should use the Microsoft.Sharepoint.LayoutsPageBase as a base class and should be content pages that reference to the ~/_layouts/application.master master page, Application Pages might include in line code or have a code behind file compiled in a dll, to deploy application pages they should be the LAYOUTS directory and all custom code dlls either in the GAC.[more]

Site Pages (Content Pages)

Site Pages can be customized on a site-by-site basis. default.aspx page in the Blank site is considered a site page as well as the AllItems.aspx used in lists. When customizing site pages this might lead to hundreds of versions of one site pages, site pages have only one physical version and all customized pages reside in the Content Database of the Web Application. This leads us to one important optimization point known as page ghosting, imagine that you have just created 100 new WSS sites from the Blank Site template. If none of these sites requires a customized version of its home page (default.aspx), would it still make sense to copy the exact same page definition file into the content database 100 times?  Of course not, rather than copying 100 version of the same page in the content database, the WSS runtime can load the page template from the file system of the Web server and use it to process any request for an uncustomized page instance. Therefore, you can say that page ghosting describes the act of processing a request for an uncustomized page instance by using a page template loaded into memory from the file system of the front-end Web server.

Security consideration : Since the site page can be customized for every customized version, a copy must be stored in the content database, which in turn raises a security issue what if a user having an administrator permission and tries to write in line code within a customized version. This security concern is dealt in WSS by having a default policy that prohibits in line scripting in site pages. The default policy also runs site pages in a no-compile mode, which means they are not compiled into DLLs.

These are also the types of pages that developers and designers can modify and edit within SharePoint Designer, because they are virtualized within the site ’ s logical architecture and live within the site collection's content database either as customized or uncustomized pages. As far as security goes, site pages should never contain inline script. While inline script will compile and execute just fine when a page is uncustomized, after the page becomes customized it is passed through SharePoint’s safe mode parser, which will throw a runtime exception if the page contains inline script. A site page may or may not become customized, but the mere fact that it is possible should be reason enough to avoid using inline script.

 

No comments:

Post a Comment