Zieglers

Just little about C#, .NET, SQL Server 2005, MOSS and SAP

SharePoint Alerts Export Import add-in Part – 2

Posted by zieglers on June 5, 2009

In this second part of the article, I’ll mention implementation details of Alerts Export/Import add-in.

Most important decision I took as for implementation was not to use code-behind. Simply I coded everything within .aspx page. Why did I do so? Well, for couple of reasons.

Firstly, this allows faster development by avoiding building VS solution and then deploying the solution. A simple page refresh will force the page recompile. If you are developing just couple of application pages, I’d say don’t waste time by building a solution and deploying it each time code-behind changes. You’ll see coding in .aspx page is much faster. Make sure you know C# syntax well ;)

Secondly, no deployment at all. Since you are directly working on page in 12 hive ADMIN folder, once you save your changes, they are already there and page will be recompiled next time you request the page.

Of course, taking this development approach or not is totally up to you. But if you haven’t tried yet, I’d say give it a try and you’ll see that your C# syntax skills will improve drastically.

Ok, Let’s get started!!!

1. First we need a blank ‘Hello World’ application page.

Since we are developing a blank application page for Central Administration Site, masterpage of our application page must be ‘admin.master‘. Also there are some specific SharePoint controls that will be used, so those must be registered as well.

Now, open up NotePad and create an empty text file and save it as Test.aspx.

a. Adding required assembly and SharePoint control references

Include following snippet to Test.aspx.

<%@ Assembly Name=”Microsoft.SharePoint.ApplicationPages.Administration, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c”%>
<%@ Page Language=”C#” AutoEventWireup=”true” Inherits=”Microsoft.SharePoint.ApplicationPages.GlobalAdminPageBase” MasterPageFile=”~/_admin/admin.master” %>
<%@ Import Namespace=”System.Net” %>
<%@ Import Namespace=”Microsoft.SharePoint” %>
<%@ Import Namespace=”Microsoft.SharePoint.Administration” %>
<%@ Import Namespace=”Microsoft.SharePoint.Utilities” %>
<%@ 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” %>
<%@ Register TagPrefix=”wssawc” Namespace=”Microsoft.SharePoint.WebControls” Assembly=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c”%>
<%@ Register TagPrefix=”wssuc” TagName=”ToolBar” src=”~/_controltemplates/ToolBar.ascx” %>
<%@ 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” %> 

b. Adding ContentPlaceHolders

Include PlaceHolderPageTitle and PlaceHolderPageTitleInTitleArea content placeholders. Former determines browser page title, latter determines application page title.

 <asp:Content ID=”PageTitle” runat=”server” ContentPlaceHolderID=”PlaceHolderPageTitle”>
    Test Page Title – AAA
</asp:Content>
<asp:Content ID=”PageTitleInTitleArea” runat=”server” ContentPlaceHolderID=”PlaceHolderPageTitleInTitleArea”>
    Test Page Title – BBB
</asp:Content>

c. Adding Main PlaceHolder

Include PlaceHolderMain content placeholder. This placeholder will hold all controls in the main page area. For our test page we only include an AP.NET Literal control to display HelloWorld message.

<asp:Content ID=”Main” ContentPlaceHolderID=”PlaceHolderMain” runat=”server”>
 <!– Use a ASP.NET Literal Control to display messages –>
 <asp:Literal ID=”litMessages” runat=”server” />
</asp:Content>

d. Adding code for page logic

Now we can start writing code for our test page. Our C# code will be in between script tags of the page. All we need to do is to assign ‘Hello World’ to messages literal control in PageLoad event.

<script runat=”server”>
   
    protected override void OnLoad(EventArgs e)
    {
        //****************************************
        // Validate the page request to avoid
        // any malicious posts
        if (Request.HttpMethod == “POST”)
            SPUtility.ValidateFormDigest();
        //****************************************
        // Validate the page request to avoid
        // any malicious posts
        if (Request.HttpMethod == “POST”)
            SPUtility.ValidateFormDigest();
        //****************************************
        // Initialize the controls on the page
        // if its not a PostBack request
        if (!(Page.IsPostBack))
        {
            litMessages.Text = “Hello World!”;
        } // end – IsPostPack
    }
   
</script>

e. Copy Test.aspx to /12/ADMIN/ folder.

That’s all for our Test application page. No deployment, no building solution.. All we need to do is to copy Test.aspx to ~/12/ADMIN/ folder. Now open your browser. Go to Central Admin site, and test your Test.aspx. (http://yourservername:centraladminportnumber/_admin/Test.aspx)

You can download Test.aspx application page here: TestASPXCode

2. Adding UI controls – SharePoint Web Application Selector

Now we have a blank application page, we can start adding UI elements one by one. It’s always a good practice to keep logically related controls in a panel. Since providing a web application is the only input for export alerts operation, we’ll have only SharePoint Web Application selector control and submit buttons on ExportAlerts page, and will keep those in an input panel as follows.

Add the following snippet in PlaceHolderMain below litMessages literal control.

<!– Use a ASP.NET Panel Control to show or hide the form from code –>
 <asp:Panel ID=”inputForm” runat=”server”>
     <table border=”0″ cellspacing=”0″ cellpadding=”0″ width=”100%”>
        <tr>
          <td>  
         
             <!– *********************************************************
                 DISPLAY THE WEB APPLICATION SELECTOR
                 USING THE InputFormSecton AND WebApplicationSelector CONTROLS.
                 
                 THE TITLE AND DESCRIPTION ARE SPECIFIED IN THE CORRESPONDING
                 ATTRIBUTES OF THE InputFormSection CONTROL, WHILE THE CONTROLS
                 THEMSELVES ARE PLACED INSIDE THE InputFormControl SECTION –>
            <wssuc:InputFormSection runat=”server”
          Title=”Web Application”
          Description=”Select a Web Application” >
                <Template_InputFormControls>
                <tr>
              <td>
                    <SharePoint:WebApplicationSelector id=”Selector” runat=”server”
                      TypeLabelCssClass=”ms-listheaderlabel”
                      AllowAdministrationWebApplication=”true” />
                    </td>
          </tr>
                </Template_InputFormControls>
         </wssuc:InputFormSection>        
            <!– ********************************************************** –>
           
         <!– ****************************
              OK AND CANCEL BUTTON SECTION –>
         <wssuc:ButtonSection runat=”server” TopButtons=”false” BottomSpacing=”5″ ShowSectionLine=”true”>
          <Template_Buttons>
           <asp:Button UseSubmitBehavior=”false” runat=”server” OnClick=”BtnSubmit_Click” Text=”<%$Resources:wss,multipages_okbutton_text%>” id=”BtnSubmitBottom” accesskey=”<%$Resources:wss,okbutton_accesskey%>” Enabled=”true”/>
          </Template_Buttons>
         </wssuc:ButtonSection>
         <!– **************************** –>
        
       </td>
     </tr>
        </table>
    </asp:Panel>

One thing to note here is that we need to provide code for ButtonClick event. So add the following to script section of the page.

    //*************************************************************
    // This method is called when the user clicks the “OK” button
    // to activate the site feature package.
    protected void BtnSubmit_Click(object sender, EventArgs e)
    {
        // Your code here
    }

 So far so good! If you have done everything w/o any mistakes your page should look as follows.

 Alerts-4

3. Adding ‘Export Alerts’ logic.

We have our application page. We have our UI elements (web application selector and submit buttons). Now it’s time to get our hands dirty! All ‘Export Alerts’ logic will be implemented in BtnSubmit_Click event.

 Ok, at this point let’s take a look at our design details once again:

A. Crawl whole web application, which means loop through all site collections and all webs underneath.

foreach –> Site Collection in WebApplication

   foreach –> Web object in Site Collection

      foreach –> alert in Alert Collection of web

               Export alert details to xml file.

B. Xml helper functions. We need helper functions to get alert property details and write them in Alerts Export xml file in a structured way. Those functions are:

CreateXmlDocument, AddChildElement, StringValueOfObject, StringValueOfAlerts

I’m not going to mention details about those helper functions since they are out of our scope. I also didn’t spend time on them to reflect a better coding practice. As a result they are very straight-forward and represent a trivial functional coding. Be my guest if you want to refactor them and make them look better :)

C. Output messages

I haven’t provided logging functionality for export alerts, since exported xml file sort of acts as log itself. Only we need to display some statistics to UI such as number of exported alerts, urls of crawled site collections and webs, execution time, … etc. For this purpose we’ll have only one string variable, namely strMessages. We’ll append any sort of execution messages to this string and then eventually assign it to litMessages.

Here is the BtnSubmit_Click code:

    //*************************************************************
    // This method is called when the user clicks the “OK” button
    // to export alerts of a selected web application.
    protected void BtnSubmit_Click(object sender, EventArgs e)
    {
        //Prepare a string object to display the result
        //of the export alerts operation for each site
        string strMessages = “”;
        // Hide input panel
        inputForm.Visible = false;
       
        try
        {
            // Execution ’start’ and ‘finish’ time variables
            DateTime start = DateTime.Now;
            DateTime finish = DateTime.Now;
            // Construct Exported Alerts Xml file name
            // Format: ddmmyyyy_hhmmss.xml
            alertsFileName = DateTime.Today.Day.ToString() +
                                    DateTime.Today.Month + DateTime.Today.Year.ToString() +
                                    “_” +
                                    DateTime.Now.Hour.ToString() +
                                    DateTime.Now.Minute.ToString() +
                                    DateTime.Now.Second.ToString() +
                                    “.xml”;
               
            // add all the alert info to an XML document
            System.Xml.XmlDocument Document = CreateXmlDocument();
            //Iterate through each of the site collections
            //in the selected web applications
            foreach (SPSite site in Selector.CurrentItem.Sites)
            {
                //Disable the CatchAccessDeniedException
                //of the site collection to avoid being redirected
                //to the “Access Denied” page if access is denied.
                site.CatchAccessDeniedException = false;
                // Display site url
                strMessages += “<br /><b> === Exporting Alerts for site: ” + site.Url + ” === </b><br />”;
                //Iterate through each site in the site collection
                foreach (SPWeb web in site.AllWebs)
                {
                    // Get all users of the web
                    SPUserCollection collUsers = web.SiteUsers;
                    // Check if there are any alerts to be exported for this web object
                    if (web.Alerts.Count > 0)
                    {
                        // create the alerts root node
                        System.Xml.XmlElement AlertsNode = AddChildElement(Document.DocumentElement, “Alerts”);
                        // Add Web Url attribute
                        System.Xml.XmlAttribute NewAttribute = AlertsNode.OwnerDocument.CreateAttribute(”WebUrl”);
                        AlertsNode.Attributes.Append(NewAttribute);
                        NewAttribute.InnerText = Convert.ToString(web.Url);
                        // Add IsRootWeb attribute
                        NewAttribute = AlertsNode.OwnerDocument.CreateAttribute(”IsRootWeb”);
                        AlertsNode.Attributes.Append(NewAttribute);
                        // Display web object info
                        strMessages += “<br /> + Web : ” + web.Url + ” + <br />”;
                        // Save Alerts to xml
                        // iterate through all the alerts for every user of a site
                        foreach (SPUser oUser in collUsers)
                        {
                            SPAlertCollection collAlerts = oUser.Alerts;
                            if (oUser.Alerts.Count > 0)
                            {
                                // Check if this web is a root web or not
                                if (site.Url == web.Url)
                                    NewAttribute.InnerText = “true”;
                                else
                                    NewAttribute.InnerText = “false”;
                                foreach (SPAlert oAlert in collAlerts)
                                {
                                    // Get alert properties
                                    StringValueOfAlerts(AlertsNode, oAlert);
                                    AlertCount++;
                                } // end – foreach SPAlert
                            } // end -if
                        } // end – foreach SPUser
                       
                    } // end – if AlertsCount
                } // end – foreach SPWeb
                port = site.Port;
                AlertsFile = AlertsDir + port.ToString() + “_” + alertsFileName;
                //Allow the site collection to continue handling
                //access denied exceptions
                site.CatchAccessDeniedException = true;
               
            } // end – foreach SPSite
            // Save Alerts Export file
            Document.Save(AlertsFile);
            strMessages += “<br /> ————————————————————————————– <br />”;
            strMessages += “<br /><b>” + AlertCount.ToString() + “</b> alerts <b><font color=green>successfully</font></b> exported for web application: <b>” + Selector.CurrentName + “</b><br />”;
            strMessages += “<br />Export file: <b>” + port.ToString() + “_” + alertsFileName + “</b><br />”;
            finish = DateTime.Now;
            TimeSpan elapsedTime = finish.Subtract(start);
            strMessages += “<br /> Exported in <b>” + elapsedTime.Minutes.ToString() + “</b> minute(s) and <b>” + elapsedTime.Seconds.ToString() + “</b> seconds and <b>” + elapsedTime.Milliseconds.ToString() + “</b> miliseconds <br />”;
           
        }
        catch (Exception AlertsSaveException)
        {
            //if an error occurs during export alerts operation;
            //capture the message to display it to the user
            //after iterating through all the sites
            strMessages += “<br />Alerts Save Error: ” + AlertsSaveException.Message + “<br />”;
        }
        // Display messages if there are any
        litMessages.Text = strMessages;
       
    }

If you are not interested in details of ‘Export Alerts‘ and just want to use it as soon as possible, you can download “AlertsSave.aspx” from this link: AlertsSaveASPX

(Copy and paste word doc contents in a text file and rename it to AlertsSave.aspx. Then copy it to ~/12/ADMIN/ folder.)

Please let me know if you run into any difficulties while trying to implement/run ‘export alerts’ functionality..

zieglers

Posted in IT Stuff, MOSS & WSS 3.0 | Tagged: , , , , , , , , | Leave a Comment »

SharePoint Alerts Export Import add-in Part – 1

Posted by zieglers on June 5, 2009

This article explains how you can develop a SharePoint Alerts Export/Import add-in for Central Administration site.

First part of the article ‘Alerst Export/Import add-in for SharePoint Part-1‘, will state the problem leading to this solution. Also, some design points will be mentioned.

Background: One of my clients had to delete subsites when a new version of a site template was developed and recreate the site using the new template. In this case, since the alerts are user/web centric when the site was deleted, they were gone. So, I needed a solution to export alerts before deletion and save them on file system. This was the first part of the scenario. Once the new site is created using the new template, it was time to import them back.

Export operation would be at web application scope. On the other hand import operation would give the flexibility of choosing subsites. Also, import file would need to be chosen among multiple exported files at different times. This would also require an upload functionality while importing. As with all upload operations, validation and extension checks were important.

Another requirement was scalability of the solution. It was expected to work for 100 000 alerts and 1000 different users. This was an optimization problem and every extra loop in the logic would cost extra.. Idea seemed simple: first export them, then selectively import. But as I went further in the implementation, I faced some challenges, unexpected object model behaviours … etc. Here i’ll try to mention everything in detail.

Design:

Solution will include two simple custom built application pages for SharePoint Central Administration Site. 

These pages will be reachable thru links in a sub-section called ‘Alerts’ in Application Management section.

Alerts-1

First application page, Export Alerts, is for exporting alerts of a selected web application. (Note that, scope here is ‘Web Application’. This means that all site collections and webs will be looped and alerts will be exported in a way that we keep hierarchy for later to be able to import selectively, namely by selecting a site collection and any web sites in it.)

Alerts-2

Second application page, Import Alerts into a Site Collection, will have three input sections. Firstly user will select a site collection. Secondly sites, alerts will be imported into, will be selected. Then, exported alerts file will be uploaded using an upload control.

At this point, necessary validations will be performed such as file extension check, file format check, file size check … etc. Once all validations are passed successfully, alerts will be imported to selected web sites.

Since import operation can be time consuming based on the number of alets being imported, SPLongOperation will be used to display on-going progress. Moreover, all errors and import operations will be logged for further investigation in case needed.

Also, for better exception handling error messages will be refactored.

Alerts-3

Implementation details are explained in Part-2 of  ’SharePoint Alerts Export Import add-in’ article.

Stay tuned.. :)

zieglers

Posted in IT Stuff, MOSS & WSS 3.0 | Tagged: , , , , , , | Leave a Comment »

Add Blog Posts web part to Team Site page

Posted by zieglers on March 5, 2009

the-computer-demands-a-blog

If you want to add posts web part to your team site – assuming that you have your blog site as subsite (named as “blog“) – you can do this as follows:

1. Create a doc library called Pages, default doc temlate is Web Part Page.
2. Create a page called Test.aspx.
3. Open Notepad, paste following web part code and save this code as Posts.webpart.

postswebpart

4. Change List ID for Posts list in blog site.
    Find 43EBBD67-B3EB-4D9F-89C7-B84520A40991 and replace with your blog site’s posts list id.

5. Then, go to your team site web part galleries and upload this Posts.webpart.

6. Add this web part to your Test.aspx.

Now you should be seeing Posts from blog site. :)

P.S. Before writing this reply, I tested above steps one by one myself and it’s working.
Let me know if you encounter any problems.

zieglers

Posted in IT Stuff, MOSS & WSS 3.0 | Tagged: , , , , | 1 Comment »

Search Contacts Web Part

Posted by zieglers on March 1, 2009

chair-contacts

For almost all implementations of SharePoint, search is a very crucial part. Most of search features come OOTB, and you need to customize it only if are not satisfied with a generic use scenario. No need to mention that first you need to crawl the content, of course.

Since all above sounds good, there are also sort of requirements that you lead to perform search against list items in your site collection. Most of the time you need to type all the word and perform a search to find what you are looking for. In such scenarios, wildcard search is becoming a challange as well.

In this post, I’ll try to show you a very straight-forward search implementation using CAML, JavaScript and Content Editor Web Part. We’ll first create a Contacts list. Then, customize a DataFormWebPart so that its data source will be responsible from our CAML queries.  Finally, using a Content Editor Web Part and JavaScript, we’ll perform search against FirstName, LastName, FullName, and Company fields.

Let’s start…

  • 1. Create Contacts list

 1_createcontactslist

  • 2. Add sample contacts.

 2_addcontacts

  • 3. Using SharePoint Designer, create a blank aspx page and name it “Results.aspx“.

 3_addnewpage

  • 4. From Data Source Library, drag and drop Contacts list to the form of the page you just created.

 4_addcontactstopage

  • 5. This will insert a DataFormWebPart into form of Results.aspx. Now, we need to edit columns so that First Name, Last Name, Full Name and Company is included.

 5_editcolumns

  • 6. Also, let’s change the layout to “two-column repeating form with border

 6_changelayout

  • 7. At the end of Results.aspx html code add the following script.

<SharePoint:CssLink runat=”server”/>

        <SharePoint:ScriptLink language=”javascript” name=”core.js” Defer=”true” runat=”server”/>

        <script type=”text/javascript”>

        function FrameGoToLink(elm) {

                        if (elm.href==null) return;

                        var targetUrl=elm.href;

                        var ch=elm.href.indexOf(”?”) >=0 ? “&” : “?”;

                        var srcUrl=ch+”Source=”+window.top.location;

                        var targetUrl=elm.href+srcUrl;

                        window.top.location = targetUrl;

        }

        </script>

 

  • 8. Add CAML Query details. Also, don’t forget to update contacts list id in the following code with contacts list id of the site you create.

a. Add Data Sources

<DataSources>

<SharePoint:SPDataSource runat=”server” DataSourceMode=”List” SelectCommand=”&lt;View&gt;&lt;Query&gt;{_1}{SearchQS}{_2}{SearchQS}{_3}{SearchQS}{_4}{SearchQS}{_5}&lt;OrderBy&gt;&lt;FieldRef Name=’Title’/&gt;&lt;FieldRef Name=’FirstName’/&gt;&lt;/OrderBy&gt;&lt;/Query&gt;&lt;/View&gt;” UseInternalName=”True” ID=”Contacts1″><SelectParameters><WebPartPages:DataFormParameter ParameterKey=”ListID” PropertyName=”ParameterValues” DefaultValue=”{1E662208-F914-45B8-BC2B-A4FB2BA594BC}” Name=”ListID”></WebPartPages:DataFormParameter><WebPartPages:DataFormParameter ParameterKey=”SearchQS” PropertyName=”ParameterValues” DefaultValue=”r” Name=”SearchQS”></WebPartPages:DataFormParameter><WebPartPages:DataFormParameter ParameterKey=”_1″ PropertyName=”ParameterValues” DefaultValue=”&lt;Where&gt;&lt;Or&gt;&lt;Or&gt;&lt;Or&gt;&lt;BeginsWith&gt;&lt;FieldRef Name=’Title’/&gt;&lt;Value Type=’Text’&gt;” Name=”_1″></WebPartPages:DataFormParameter><WebPartPages:DataFormParameter ParameterKey=”_2″ PropertyName=”ParameterValues” DefaultValue=”&lt;/Value&gt;&lt;/BeginsWith&gt;&lt;BeginsWith&gt;&lt;FieldRef Name=’FirstName’/&gt;&lt;Value Type=’Text’&gt;” Name=”_2″></WebPartPages:DataFormParameter><WebPartPages:DataFormParameter ParameterKey=”_3″ PropertyName=”ParameterValues” DefaultValue=”&lt;/Value&gt;&lt;/BeginsWith&gt;&lt;/Or&gt;&lt;BeginsWith&gt;&lt;FieldRef Name=’Company’/&gt;&lt;Value Type=’Text’&gt;” Name=”_3″></WebPartPages:DataFormParameter><WebPartPages:DataFormParameter ParameterKey=”_4″ PropertyName=”ParameterValues” DefaultValue=”&lt;/Value&gt;&lt;/BeginsWith&gt;&lt;/Or&gt;&lt;BeginsWith&gt;&lt;FieldRef Name=’FullName’/&gt;&lt;Value Type=’Text’&gt;” Name=”_4″></WebPartPages:DataFormParameter><WebPartPages:DataFormParameter ParameterKey=”_5″ PropertyName=”ParameterValues” DefaultValue=”&lt;/Value&gt;&lt;/BeginsWith&gt;&lt;/Or&gt;&lt;/Where&gt;” Name=”_5″></WebPartPages:DataFormParameter>

                                    </SelectParameters><UpdateParameters><WebPartPages:DataFormParameter ParameterKey=”ListID” PropertyName=”ParameterValues” DefaultValue=”{1E662208-F914-45B8-BC2B-A4FB2BA594BC}” Name=”ListID”></WebPartPages:DataFormParameter>

                                    </UpdateParameters><InsertParameters><WebPartPages:DataFormParameter ParameterKey=”ListID” PropertyName=”ParameterValues” DefaultValue=”{1E662208-F914-45B8-BC2B-A4FB2BA594BC}” Name=”ListID”></WebPartPages:DataFormParameter>

                                    </InsertParameters><DeleteParameters><WebPartPages:DataFormParameter ParameterKey=”ListID” PropertyName=”ParameterValues” DefaultValue=”{1E662208-F914-45B8-BC2B-A4FB2BA594BC}” Name=”ListID”></WebPartPages:DataFormParameter>

                                    </DeleteParameters>

            </SharePoint:SPDataSource>

</DataSources>

b. Add Parameter Bindings

Note that below, we define our CAML query WHERE clause.

<ParameterBindings>

                                    <ParameterBinding Name=”dvt_apos” Location=”Postback;Connection”/>

                                    <ParameterBinding Name=”UserID” Location=”CAMLVariable” DefaultValue=”CurrentUserName”/>

                                    <ParameterBinding Name=”Today” Location=”CAMLVariable” DefaultValue=”CurrentDate”/>

                                    <ParameterBinding Name=”ListID” Location=”None” DefaultValue=”{1E662208-F914-45B8-BC2B-A4FB2BA594BC}”/>

                                    <ParameterBinding Name=”SearchQS” Location=”QueryString(Search)” DefaultValue=”r”/>

                                    <ParameterBinding Name=”_1″ Location=”QueryString(ReturnAll)” DefaultValue=”<Where><Or><Or><Or><BeginsWith><FieldRef Name=’Title’/><Value Type=’Text’>”/>

                                    <ParameterBinding Name=”_2″ Location=”QueryString(ReturnAll)” DefaultValue=”</Value></BeginsWith><BeginsWith><FieldRef Name=’FirstName’/><Value Type=’Text’>”/>

                                    <ParameterBinding Name=”_3″ Location=”QueryString(ReturnAll)” DefaultValue=”</Value></BeginsWith></Or><BeginsWith><FieldRef Name=’Company’/><Value Type=’Text’>”/>

                                    <ParameterBinding Name=”_4″ Location=”QueryString(ReturnAll)” DefaultValue=”</Value></BeginsWith></Or><BeginsWith><FieldRef Name=’FullName’/><Value Type=’Text’>”/>

                                    <ParameterBinding Name=”_5″ Location=”QueryString(ReturnAll)” DefaultValue=”</Value></BeginsWith></Or></Where>”/>

            </ParameterBindings>

 

  • 9. Then, save page as “Results.aspx“.

 8_saveas

  • 10. Go to home page and add a Content Editor Web Part.

 9_addcewp

  • 11. Edit CEWP properties and add the following to its Source Editor.

<div style=”height:400px;”>

                        <script type=”text/javascript”>

                                        var timeout = -1;

                                        function searchChange(textbox) {

                                                        var text = textbox.value;

                                                        if (timeout != -1) clearTimeout(timeout);

                                                        timeout = setTimeout(”commitSearch(’” + text + “‘)”, 400);

                                        }

                                        function commitSearch(text) {

                                                        var frame = document.getElementById(”contactFrame”);

                                                        if (text == “”) frame.src = “/Results.aspx?ReturnAll=Yes”;

                                                        else frame.src = “/Results.aspx?Search=” + text;

                                        }

                        </script>

    <div class=”ms-listdescription”>Use the text field below to search for contacts by First Name, Last Name, Full Name, or Company.</div>

    <input type=”text” style=”border:1px gray solid;” id=”contactSearch” name=”contactSearch” onkeyup=”searchChange(this);”/><br/>

                        <iframe id=”contactFrame” style=”width:100%; height: 100%; margin-bottom:-30px; padding-bottom:30px;” src=”/Results.aspx?ReturnAll=Yes” scrolling=”auto” frameborder=”no”>

                        </iframe>

                        </div>

 10_sourceeditor

  • 12. That’s all. Now you can test. Go to homepage and type something in search textbox. You’ll realize that results will be updated as you type.

 11_results1

 12_results2

zieglers

Posted in IT Stuff, MOSS & WSS 3.0 | Tagged: , , , , , , , , , | Leave a Comment »

Featured Employee Web Part – AJAX Enabled

Posted by zieglers on February 18, 2009

Abstract: This document explains how to develop AJAX Enabled Featured Employee Web Part for SharePoint 2007. This web part displays a random employee profile after every 5 seconds using ASP.NET AJAX Technology.

Introduction

In this article, I’ll try to explain how to implement AJAX enabled “Featured Employee” web part. Actually what I mean by featured employee is any user profile which exists in SharePoint Shared Services user profiles list.

In most of the projects I worked, clients were asking for a web part which sort of displays or searches based on user profile info stored in Active Directory. I’ll try to show how to implement “Employee Directory Search” web part in another article. For this one, I’ll focus on just displaying employee info.

Let me mention some features of this web part. First of all, this web part will be changing displayed profile every 5 seconds using ASP.NET AJAX 1.0. Profiles will be displayed in a random fashion. Also, there is going to be a Department property to limit displayed profiles to a certain department of the company.

Department

Before we start, I’d like to show you how “Featured Employee” web part will look like once we are done. (After every 5 seconds, displayed profile will be randomly changed.)

Featured Employees

Design

Design of this web part can be divided into some sub sections as follows:

1. Implementing Featured Employee web part without AJAX capability

a. Get a list of user profiles and keep them in a collection

b. Filter user profiles based on following properties

i. Department (This is our first criteria. If user belongs to the department specified by web part properties pane, then include this user to “Displayable” collection)

ii. Photo Exists (Don’t display profiles w/o photo)

iii. Visible (If this additional ‘Visible’ Boolean property is true in user’s profile, then display this profile)

c. Randomly select only one employee profile

d. Display UI using control template

 

2. Adding AJAX capability

a. Enable SharePoint site for AJAX

i. Install ASP.NET AJAX 1.0

ii. Add necessary Web.Config entries

iii. Add Script Manager to master page

b. Create an Update Panel

c. Create a Timer and Event Handler for re-displaying profiles after each 5 sec.

d. Add code implemented in subsection 1 above to Update Panel.

First we will implement this web part as it will only display different employee profiles after every page load. Then, we will extend this functionality using AJAX.

Now, let’s start with the implementation of sub section 1.

Implementation

Implementing Featured Employee web part without AJAX capability

Get a list of user profiles and keep them in a collection

UserProfileManager profileManager = new UserProfileManager(ServerContext.Current);

Filter user profiles based on following properties

i. Department (This is our first criteria. If user belongs to the department specified by web part properties pane, then include this user to “Displayable” collection)

Department User Profile Property

ii. Photo Exists (Don’t display profiles w/o photo)

Picture

iii. Visible (If this additional ‘Visible’ Boolean property is true in user’s profile, then display this profile)

Visible Property

private void FillDataListWithUserData(BaseDataList list)

{

// Get max number for randomazition

int max = 0;

ArrayList upc = new ArrayList();

 

foreach (UserProfile profile in profileManager)

// In order to show employee profile in web part,

// there should be a department value and this profile should be flagged as visible

if (Parse<String>(profile["Department"]) != null

&& Parse<Boolean>(profile["VisibleInFaceBook"])

&& Department == Parse<String>(profile["Department"]))

{

// Add qualified user profile to list

upc.Add(profile);

max++;

}

 

}

Randomly select only one employee profile

// Generate a random index

Random random = new Random();

int randomIdx = random.Next(0, max);

 

int i = 0;

foreach (UserProfile profile in upc)

if (i == randomIdx)

{

users.Add(new FaceBookUser()

{

Name = Parse<String>(profile["PreferredName"]),

FirstName = Parse<String>(profile["FirstName"]),

LastName = Parse<String>(profile["LastName"]),

Department = Parse<String>(profile["Department"]),

Office = Parse<String>(profile["Office"]),

Photo = Parse<String>(profile["PictureURL"]),

AboutMe = Parse<String>(profile["AboutMe"]),

Title = Parse<String>(profile["Title"]),

MySiteUrl = Parse<String>(profile["PersonalSpace"]),

HireDate = Parse<DateTime>(profile["SPS-HireDate"])

});

break;

}

else

i++;

}

 

Display UI using control template

protected override string DeterminateView()

{

return @”~/_controltemplates/FaceBookWebPartControl.ascx”;

}

Adding AJAX capability

Enable SharePoint site for AJAX

i. Download & Install ASP.NET AJAX 1.0

Can be downloaded from Microsoft Download Center: http://www.microsoft.com/downloads/details.aspx?FamilyID=ca9d90fa-e8c9-42e3-aa19-08e2c027f5d6&displaylang=en

ii. Add necessary Web.Config entries

You can follow the post I wrote in my blog for that:

http://zieglers.wordpress.com/2009/02/02/webconfig-entries-for-enabling-ajax-for-sharepoint-2007/

iii. Add Script Manager to master page

Add the following entry to the master page of the page which hosts Featured Employee web part:

<asp:ScriptManager runat=”server” ID=”ScriptManager1″></asp:ScriptManager>

ScriptManager in master page

Create an Update Panel

Now, we need an Update Panel in which contents of the web part will be displayed.

protected override void CreateChildControls()

{

base.CreateChildControls();

this.EnsureUpdatePanelFixups();

UpdatePanel up = new UpdatePanel();

up.ID = “UpdatePanel1″;

up.ChildrenAsTriggers = true;

up.UpdateMode = UpdatePanelUpdateMode.Conditional;

this.Controls.Add(up);

up.ContentTemplateContainer.Controls.Add(this.lstEmployeesList);

}

Note above that we add lstEmployeeList DataList to update panel container. This list is holding employee profiles to be displayed.

Create a Timer and Event Handler for re-displaying profiles after each 5 sec.

We also need a timer to fire the event which will be changing displayed profile after every 5 seconds.

Timer timer = new Timer();

timer.Interval = 5000;

timer.Tick += new EventHandler<EventArgs>(HandleButtonClick);

up.ContentTemplateContainer.Controls.Add(timer);

Display Employee Profile Event Handler

So, this timer will call HandleButtonClick event handler every 5 seconds and will change displayed profile. It does nothing but calls FillDataWithUserData to get lstEmployeeList DataList filled with new employee profile.

private void HandleButtonClick(object sender, EventArgs eventArgs)

{

using (SPWeb web = SPContext.Current.Site.OpenWeb())

{

// Change displayed user profile each time clock ticks

FillDataListWithUserData(lstEmployeesList);

}

}

Helper Code

This implementation makes use of some helper code.

Our first helper class is actually a base web part class. (BaseWebPart.cs)

Second helper class is just an entity class to hold some employee profile information. (FaceBookUser.cs)

Helper classes

Conclusion

As a result, we have an AJAX enabled web part displaying random employee profiles every 5 sec. from a selected department. This web part can be used at internal department sites of companies. It can also be useful for pages such as “contact us”, “board of directors”, “primary client contacts”… etc.

 

Posted in C#, IT Stuff, MOSS & WSS 3.0 | Tagged: , , , | Leave a Comment »

How to filter list values based on current user profile? UserContextFilter Web Part

Posted by zieglers on February 17, 2009

In this article I’ll try to show you how to use UserContextFilter web part. UserContextFilter web part can be used in situations where you’d like to filter other web parts based on a property value of the current user. Mostly this filter criterion is current user id. However, in some cases one may need to use any of the user profile property values such as Title, Department, and Email … etc.

For this article I chose a simple scenario: We’ll add a Tasks web part and by using UserContextFilter web part only tasks assigned to current user will be shown.

Here are the details:

  • 1. Create a Team Site and delete all web parts on default.aspx page.

101

  • 2. Add Tasks web part.

 102

  • 3. Add Current User Filter WP.

103

This web part is only viewable in edit mode, and it needs to be configured prior to use.

104

  • 4. Add a connection to Tasks web part.

 1051

  • 5. Select “Assigned To” as Consumer Field Name and click “Finish”.

106

107

  • 6. Test UserContextFilter web part.
  • a. Create a test user called “testuser

 108

  • b. Assign this user to the test site’s visitors group.

 109

 110

  • c. Before signing in as testuser, create a sample task for this user.

 111

  • d. Now sign in as test user. Tasks web part, which is being filtered by UserContextFilter web part, should be displaying testuser’s tasks as follows.

112

113

zieglers

Posted in IT Stuff, MOSS & WSS 3.0 | Tagged: , , , , , , | Leave a Comment »

Web.Config entries for enabling AJAX for SharePoint 2007

Posted by zieglers on February 2, 2009

   There are several steps to be followed when you want to enable AJAX for SharePoint 2007 such as installing Microsoft ASP.NET AJAX 1.0 and referencing AJAXControlToolkit.dll in your Visual Studio Web Part project. However, I think the most important part is providing required web.config entries. Most of the problems encountered during the process of enabling AJAX for SharePoint 2007 results from missing entries in web.config. That’s why I wanted to list them as follows:

 

Extending SharePoint web.config files with Microsoft ASP.NET AJAX 1.0

In order to enable and leverage ASP.NET AJAX capabilities for SharePoint 2007, some entries must be added to web.config file. 

 

1. Add a <sectionGroup> element to the <configSections> tag:

 

<configSections>   

    <sectionGroup name=”system.web.extensions” type=”System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″>
      <sectionGroup name=”scripting” type=”System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″>
          <section name=”scriptResourceHandler” type=”System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ requirePermission=”false” allowDefinition=”MachineToApplication”/>
        <sectionGroup name=”webServices” type=”System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″>
          <section name=”jsonSerialization” type=”System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ requirePermission=”false” allowDefinition=”Everywhere” />
          <section name=”profileService” type=”System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ requirePermission=”false” allowDefinition=”MachineToApplication” />
          <section name=”authenticationService” type=”System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ requirePermission=”false” allowDefinition=”MachineToApplication” />
        </sectionGroup>
      </sectionGroup>
    </sectionGroup>
</configSections>   

 

2. Add a <controls> section as a child of the <system.web>/<pages> tag.

 

    <pages>
      <controls>
        <add tagPrefix=”asp” namespace=”System.Web.UI” assembly=”System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″/>
      </controls>
   
</pages>   


3. Add the following tag to the <assemblies> tag, within <compilation>:


      <assemblies>
       <add assembly=”System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″/>
     
</assemblies>


4. Add some new registrations to the end of the <httpHandlers> section:


 <httpHandlers>
      <add verb=”*” path=”*.asmx” validate=”false” type=”System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″/>
      <add verb=”*” path=”*_AppService.axd” validate=”false” type=”System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″/>
      <add verb=”GET,HEAD” path=”ScriptResource.axd” type=”System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ validate=”false”/>
  </httpHandlers>

 

5. Add a new registration to the HttpModules section, beneath any existing registrations.


  <httpModules>
      <add name=”ScriptModule” type=”System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″/>
  </httpModules>


 

6. Add a SafeControl entry for the System.Web.UI namespace from Microsoft Ajax Extensions, within the <SharePoint>/<SafeControls>section:


  <SafeControls>
      <SafeControl Assembly=”System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ Namespace=”System.Web.UI” TypeName=”*” Safe=”True” />
  </SafeControls>

 

7. Finally, add the following configuration tags at the bottom of web.config, near the bottom before the end <configuration> tag.


  <system.web.extensions>
    <scripting>
      <webServices>
      <!– Uncomment this line to enable the authentication service. Include requireSSL=”true” if appropriate. –>
      <!–
        <authenticationService enabled=”true” requireSSL = “true|false”/>
      –>
      <!– Uncomment these lines to enable the profile service. To allow profile properties to be retrieved and modified in ASP.NET AJAX applications, you need to add each property name to the readAccessProperties and writeAccessProperties attributes. –>
      <!–
      <profileService enabled=”true”
                      readAccessProperties=”propertyname1,propertyname2″
                      writeAccessProperties=”propertyname1,propertyname2″ />
      –>
      </webServices>
      <!–
      <scriptResourceHandler enableCompression=”true” enableCaching=”true” />
      –>
    </scripting>
  </system.web.extensions>
  <system.webServer>
    <validation validateIntegratedModeConfiguration=”false”/>
    <modules>
      <add name=”ScriptModule” preCondition=”integratedMode” type=”System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″/>
    </modules>
    <handlers>
      <remove name=”WebServiceHandlerFactory-Integrated” />
      <add name=”ScriptHandlerFactory” verb=”*” path=”*.asmx” preCondition=”integratedMode”
           type=”System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″/>
      <add name=”ScriptHandlerFactoryAppServices” verb=”*” path=”*_AppService.axd” preCondition=”integratedMode” type=”System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″/>
      <add name=”ScriptResource” preCondition=”integratedMode” verb=”GET,HEAD” path=”ScriptResource.axd” type=”System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ />
    </handlers>
  </system.webServer>

 

Adding a ScriptManager into a SharePoint MasterPage

 

Add the following into the markup of your master page.  A recommended location is right beneath the WebPartManager registration (search for  <WebPartPages:SPWebPartManager id=”m” runat=”Server” />):

    <asp:ScriptManager runat=”server” ID=”ScriptManager1″></asp:ScriptManager>

 

zieglers

 

Posted in IT Stuff, MOSS & WSS 3.0 | Tagged: , , , , , , , | 1 Comment »

Updating List ID values in DataFormWebPart after import operation

Posted by zieglers on January 29, 2009

For the last couple of months, I’ve been developing some POC SharePoint VPCs for clients. Mostly they were publishing sites with lots of UI and functionality customization. Once the development was over, I had to prepare deployment packages for delivery to client environment.

At this point I had mainly two choices for deployment. I could either do export – import operation, or develop features for creating publishing site, custom lists, master pages, layouts and web parts. I’ve tried both approaches and they have their own pros and cons. However, what I’d like to mention in this post is updating list ids.

Doesn’t matter which approach I took, every time I had to update List ID values of content query web parts and dataform web parts. The reason is List ID values in those web parts were still pointing to exported site’s List GUDs.

Manually updating those values is a solution, however it’s time consuming and not practical after importing a number of sites. After some reseach and trials, finally I figured out how to update List IDs automatically.

In order to achieve this, I’m using two main tools:

1. Gary Lapointe’s stsadm extensions: replacewebpartcontent command for replacing old List ID value with new one

http://stsadm.blogspot.com/2007/10/replace-web-part-content.html

http://stsadm.blogspot.com/2007/10/retarget-content-query-web-part.html

Download and install Stsadm Extensions from Gary Lapointe’s blog: http://stsadm.blogspot.com/

2. PowerShell scripting: getting new List ID after importing the site or activating feature which creates custom lists used in the site.

Ok, now let’s get our hands dirty…

1. Introduction

Scenario is as follows: We have imported our sample publishing site and necessary lists have been created. You go to the site and see the error messages in dataform web parts saying that:

“Unable to display this Web Part. To troubleshoot the problem, open this Web page in a Windows SharePoint Services-compatible HTML editor such as Microsoft Office SharePoint Designer. If the problem persists, contact your Web server administrator.”

Say, we have a sample web part named MyDataFormWP on home page of the site. Also this dataform web part is using our sample list named MySampleList. Also let’s assume that just imported publishing site hosted at this url: http://myservername:1000.

2. Getting new List ID using PowerShell

(If you haven’t done so yet, download PowerShell from Microsoft Download Center and install it.)

At this point I need to know the list id of recently created MySampleList. This is going to be passed to replacewebpartcontent command as a replacestring parameter. In order to do so, “SharePoint should be ready to take off…” :) What this means is explained in this article: http://cglessner.blogspot.com/2008/06/powershell-sharepoint.html 

You can also download this profile file from: http://www.codeplex.com/iLoveSharePoint/Release/ProjectReleases.aspx?ReleaseId=14994

powershell

Once you apply the steps explained in the above article and set up your powershell profile for sharepoint, now you can easily get the List ID of lists you want.

Just run these two lines:

$list = get-splist -webUrl http://myservername:1000 -listName MySampleList
[String]$list.ID

newlistid

Now, we now our new list ID and ready to pass this as parameter to replacewebpartcontent command.

3. Replacing List ID value in DataForm Web Part

Here is the syntax of replacewebpartcontent command’s usage:

stsadm -o gl-replacewebpartcontent -url http://myservername:1000/HomePage.aspx -webpartname MyDataFormWP -searchstring “xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx” -replacestring $list.ID -publish -scope page

-url parameter: web page url hosting our sample web part

-webpartname parameter: obviously the name of web part whose list id we would like to update

-searchstring parameter: old list id. This is the only static parameter that we need to provide to this command. You can find old list id by exporting the web part on the page and searching for List ID value in it.

-replacestring parameter: This is our new list id which we obtained above using PowerShell commands.

4. Putting it all together: Passing webUrl as parameter to PowerShell script

Until now all steps explained above are individual automations. We can put everything together into a PowerShell script. Here is a sample one: MyScript.ps1

=== MyScript.ps1 ===

 Param($webUrl)

$list = get-splist -webUrl $webUrl -listName MySampleList
[String]$list.ID
stsadm -o gl-replacewebpartcontent -url $webUrl/HomePage.aspx -webpartname MyDataFormWP -searchstring xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -replacestring $list.ID -publish -scope page

================

To execute this script (assuming MyScript.ps1 file is in the same folder), simply run the following command from Command Prompt:

PowerShell -command .\MyScript.ps1 -webUrl http://myservername:1000

That’s all… :) Hope it works for you as well..

There are couple of enhancements to do here as well.

1. Search string (old list ID) can be found automatically

2. Web part names or old list ids can be read from an input file or passed as other parameters.

I’ll try to enhance this approach once I have more time to spend on it. As for now, this much automation works for my deployment scenarios. Please feel free to share any comments, ideas or other possible approaches.

zieglers

Posted in IT Stuff, MOSS & WSS 3.0 | Tagged: , , , , , , , | Leave a Comment »

Encrypt / Decrypt Connection Strings in web.config

Posted by zieglers on October 27, 2008

Key Maker

Key Maker

ASP.NET stores all the configuration information in plain text files called web.config and machine.config files. We store all vital information including database connection strings, user names, passwords for the databases. Thus you end up storing all sensitive information in vulnerable plain text files which is nothing but security compromise.

If you want to secure your connection strings and application settings, here is an easy way to encrypt / decrypt sections in web.config file. You can use aspnet_regiis.exe command line tool as follows:

Encrypting appSettings and connectionStrings sections in web.config :

Aspnet_regiis.exe –pef “appSettings” “<PathToWebSiteDir>” –prov “DataProtectionConfigurationProvider”

Aspnet_regiis.exe –pef “connectionStrings” “<PathToWebSiteDir>” –prov “DataProtectionConfigurationProvider” 

Decrypting appSettings and connectionStrings sections in web.config :

Aspnet_regiis.exe –pdf “appSettings” “<PathToWebSiteDir>”

Aspnet_regiis.exe –pdf “connectionStrings” “<PathToWebSiteDir>”

zieglers

Posted in .NET Framework, IT Stuff | Tagged: , , , , , | Leave a Comment »

Hiding Left Navigation Frame and Quick Launch Bar – MOSS

Posted by zieglers on October 20, 2008

Hi,

I just wanted to give a quick tip on how to

  • hide left navigation frame
  • hide quick launch bar
  • hide recycle bin

in MOSS pages.

There are a lot of solutions out there to above stated desired look & feel. They have all their pros and cons, of course. However, I won’t discuss any of those. I just want to share my approach. Hopefully the easiest one :)

Step-1: Create Alternate CSS file:

For this part, all you need to do is copy the following lines to an empty txt file and rename it to myAlternateCSS.css. First one hides Recycle Bin, second hides View All Site Content link, and third one hides the whole Left Navigation Frame. You can include/exclude any of those according to your needs. 

div.ms-quicklaunch table.ms-recyclebin {
display: none;
}

#ctl00_PlaceHolderLeftNavBar_idNavLinkViewAll {
       Visibility:hidden;
}

.ms-navframe {
 display:none;
}

Alternate CSS File

 

Step-2: Upload CSS file to any document library:

After creating necessary css file, we need to upload it to any document library so that we can provide its URL to AlternateCssUrl property of the website.

 

Step-3: Change AlternateCssUrl of the site:

Although you can do this programmatically, alternatively I want to show how we can make use of SharePoint Branding Tool. This tool is so easy to use and gives you a lot of flexibilty while,

* modifying Themes,
* modifying MasterUrl (Master Page),
* modifying CustomMasterUrl (System Master Page),
* modifying SiteLogoUrl (Site Logo),
* modifying SiteLogoDescription (Site Logo Alternative Text),
* modifying AlternateCssUrl (Custom CSS Style Sheet).

You can got it from its CodePlex site:

http://www.codeplex.com/BrandingTool

http://www.codeplex.com/BrandingTool/Release/ProjectReleases.aspx?ReleaseId=14392

After running this tool, all you need to do is to open your MOSS site, select the site you want to edit and enter the URL to css file created and uploaded above.

SharePoint Branding Tool

SharePoint Branding Tool

In the above screenshot,

Moss Server Name: Server

Document Library Name (for uploading our alternate CSS file): Styles

Alternate CSS File Name: myAlternateCSS.css

After entering Alternate CSS Url and selecting the site you want to apply the sytlesheet, simply click “Apply to Selected Sites” button, and then go to your site home page.. That’s it.. ;-)

Hope it works for you :-)

Please let me know if you have troubles applying this approach.

zieglers

Posted in IT Stuff, MOSS & WSS 3.0 | Tagged: , , , , , , , , | Leave a Comment »