Search

rafelo

Advancing Productivity and Operational Efficiency through Cloud Services and Apps

Month

June 2008

Web 2.0 and the Separation of Content and Form

I’ve been giving some thought to the whole “Web 2.0” concept; how people throw the term around in technical conversations the same way they do “governance”, “collaboration”, “KPIs”, and “B2B”. I love it when terms like this come around, seeing how they are used in conversation, the meaning they are given by different people. It really trips me out.

So after reading the term for the 100th time in some random blog. I decided to search on it, and see what other people are saying. I don’t want to bore you with all the details of what I found, (I doubt there are many people out there as easily amused) but I do recommend you check out this you tube video published by a professor of Cultural Anthropology from Kansas State University. It is one of the coolest presentations I’ve seen on… well… how do I say this in the least possible geeky way?… I cant; Separation of Content and Form. I know it may not sound very fun or interesting, but check it out, I thought it was fantastic:

How to Add Menu Items to SharePoint with Features, Custom Actions, and Custom Action Groups

In my previous post, “Hidden SharePoint Lists, Fields, and Other Advanced List Settings”, I demonstrated how we can develop a custom application page to easily expose and modify list and field settings. But once the custom application page has been created, how do we expose it to our users? Ideally we would create links to our Application Pages by adding new menu item entries to the SharePoint Site Settings and Site Actions menus. Fortunately, SharePoint allows us to do just that via Features and the CustomActionGroup and CustomAction elements.

The CustomAction element refers to the actual link or menu item.

image

The CustomActionGroup element, as Microsoft puts it, “contains the core definition for a grouping of custom actions.” Such as when you see a group of links or menu items grouped together in the “Operations” and “Application Management” pages of the Central Administration site.

image

What about the “Site Actions”, list or library “Actions” and “Settings” menus? These, like most other SharePoint menus, can also be configured via CustomActions. 

image image

The following steps demonstrate how we can use features and CustomActions to add a new menu item to the Site Settings page.

Creating the Feature

  1. Browse to the file system Feature folder located in “C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\”
  2. Create a new folder for your feature. In my case I will call it “AdvancedListSettings” as I will use the feature to add a link to the Custom Application Page I created in my previous post; Hidden SharePoint Lists, Fields, and other Advanced List Settings
  3. Open the folder and create a new empty file naming it FEATURE.xml

    image

  4. Open the file and paste the following XML, replacing NEWGUID with a newly generated GUID. 

    <Feature xmlns="http://schemas.microsoft.com/sharepoint/”
      Id=”NEWGUID”
      Title=”Advanced List Settings Menu”
      Description=”This Feature adds a new menu item to the Site Settings page”
      Hidden=”FALSE”
      Scope=”Web”
      Version=”1.0.0.0″>
       
           
       

    I like to call this file the “feature definition file”. It contains the general settings of our feature such as; title, description, feature scope, and whether or not the feature is hidden; but it doesn’t necessarily contain any of the “meat” or instructions for the feature, we’ll put those in our Elements Manifest file which we’ll create next.

     

  5. Save and close the file
  6. Create another file and name it “CustomMenuItem.xml”, we’ve specified this as an Elements Manifest file in our feature definition.
  7. Open the file and paste the following XML

    <Elements
        xmlns=”http://schemas.microsoft.com/sharepoint/”>
        <CustomAction
            Id=”AdvancedListSettings”
            GroupId=”SiteAdministration”
            Location=”Microsoft.SharePoint.SiteSettings”
            RequireSiteAdministrator=”TRUE”
            Sequence=”1″
            Title=”Advanced List Settings”>
            <UrlAction
                Url=”_layouts/AdvancedListSettings.aspx” />
       

     

  8. Looking at out CustomAction element the attributes break down as follows:
    • ID – The ID specifies a unique identifier for the custom action, keep in mind that it must be unique, you may want to use a GUID.
    • GroupID – Identifies an action group that contains the action, for example, "SiteManagement". If contained within a custom action group, the value of the GroupId attribute must equal the group ID of the CustomActionGroup element.
    • Location – Specifies the location of this custom action. In this example we specified “Microsoft.SharePoint.SiteSettings", which tells SharePoint to create the custom action in the Site Settings Page.

      Note: Click here for the default list of Locations and ID’s

    • Sequence – Indicates what position the custom action should be placed in regards to other custom actions that may be in the same group.
    • Title – Gives it the text to display
  9. Save and close the file.
  10. Open the command prompt and execute the following command to install the feature:

    stsadm -o installfeature -file AdvancedListSettings

    Where “AdvancedListSettings” is the name of the new feature folder in “C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\”

  11. Browse to the Site Settings page of one of the SharePoint sites in Internet Explorer and click on the “Site Features” link

     image

  12. Click the “Activate”  button next to the new feature

    image

  13. Go back to the Site Settings page to see your new menu item / custom action.

    image 

To create a new section in the site settings page and have the link appear in that new section, the elements manifest file (i.e. CustomMenuItem.xml in this example) would have too look as follows:

<Elements
    xmlns=”http://schemas.microsoft.com/sharepoint/”>
    <CustomActionGroup
        Id=”SiteListandLibrarySettings”
        Location=”Microsoft.SharePoint.SiteSettings”
        Title=”Site List and Library Settings”
        Sequence=”1″ />
    <CustomAction
            Id=”AdvancedListSettings”
            GroupId=”SiteListandLibrarySettings”
            Location=”Microsoft.SharePoint.SiteSettings”
            RequireSiteAdministrator=”TRUE”
            Sequence=”1″
            Title=”Advanced List Settings”>
            <UrlAction
                Url=”_layouts/AdvancedListSettings.aspx” />
   

Notice the new CustomActionGroup element, it uses many of the same attributes of the CustomAction element. The GroupID attribute of the CustomAction element now references the ID of newly created CustomActionGroup.

For additional information see Custom Action Definitions in the SharePoint General Reference section of the MSDN:
http://msdn.microsoft.com/en-us/library/ms465980.aspx

Technorati Tags: SharePoint, WSS, MOSS, FEATURES

Hidden SharePoint Lists, Fields, and other Advanced List Settings

We often have to create solutions involving hidden lists and libraries. If our hidden list is part of a SharePoint feature, we would probably handle the logic of hiding the list during our feature activation routine. But what if the solution is not part of a feature? Maybe the lists where created using the browser. What if we need to make our hidden list visible to help troubleshoot something that has gone wrong?

I’ve create a SharePoint Application Page that uses the SharePoint Object Model and a series of ASP.Net controls to display and modify properties of SharePoint Lists and Fields in a site. For security reasons only users with full control of the site can access the page.

The user can select the list from an ASP.Net list control. Upon selecting the list, the page exposes the Hidden, AllowDeletion, RequestAccessEnabled, and AllowEveryoneViewItems properties of the selected list.

image

I expose the list fields during the same time (when the user selects a list.) Upon selecting a field from the list, the page exposes the Hidden property of the selected field.

image

The following is the code for the application page:

private const string webAppPropertyKey = “Custom404Path”;

protected override void OnLoad(EventArgs e)
{
    using (SPWeb site = SPContext.Current.Site.OpenWeb())
    {
        //****************************************
        // Validate the page request to avoid
        // any malicious posts
        if (Request.HttpMethod == “POST”)
            SPUtility.ValidateFormDigest();

        //****************************************
        // Get a reference the roles that are
        // bound to the user and the role
        // definition to which we need to verify
        // the user against
        SPRoleDefinitionBindingCollection usersRoles = site.AllRolesForCurrentUser;
        SPRoleDefinitionCollection siteRoleCollection = site.RoleDefinitions;
        SPRoleDefinition roleDefinition = siteRoleCollection[“Full Control”];

        //Check if the user is in the role
        if ((usersRoles.Contains(roleDefinition)) || site.CurrentUser.IsSiteAdmin)
        {
            //*******************************
            //Check if post back to run
            //code that initiates the page
            if (IsPostBack != true)
            {
                InitPage();
            }
        }
        else
        {
            Response.Redirect(“/_layouts/accessdenied.aspx”);
        }
    }
}

//*********************************************
// This method populates the listbox with
// all of the lists(SPList) in the site(SPWeb)
public void InitPage()
{
    //Get a reference to the SPWeb object
    using (SPWeb site = SPContext.Current.Site.OpenWeb())
    {
        //Iterate through each of the lists(SPList) in the site
        foreach (SPList thislist in site.Lists)
        {
            //Create a listItem for each list.
            //Set the “text” property to the title
            //and the value to the list ID
            //we will use the list ID to retrieve the
            //list settings when the user selects it
            ListItem item = new ListItem(thislist.Title, thislist.ID.ToString());
            lstSiteLists.Items.Add(item);
        }
    }
}

//*************************************************
// This method retrieves some of the list settings
// that are not accessible via the site or list settings
// pages on the SharePoint site
public void GetListSettings(object sender, System.EventArgs e)
{
    //make the list settings panel visible
    //and enable to the “Update List” button
    pnlListSettings.Visible = true;
    btnUpdateList.Enabled = true;

    //get the ID of the selected list
    Guid listGuid = new Guid(lstSiteLists.SelectedValue);

    //get a reference to the site(SPWeb) object
    using (SPWeb site = SPContext.Current.Site.OpenWeb())
    {
        //get a reference to the list object using
        //the list ID
        SPList list = site.Lists[listGuid];

        //Retrieve and display the ID, template name,
        //and template type of the list
        lblListGUID.Text = list.ID.ToString();
        lblListBaseTemplate.Text = list.BaseTemplate.ToString();
        lblListBaseType.Text = list.BaseType.ToString();

        //check the “Hidden”, “AllowDelete”, “RequestAccessEnabled”
        //and “AllowEveryOneviewItems” properties of the list and
        //update the corresponding checkboxes accordingly
        chkListHidden.Checked = list.Hidden;
        chkListAllowDelete.Checked = list.AllowDeletion;
        chkListAllowRequestAccess.Checked = list.RequestAccessEnabled;
        chkAllowEveryoneViewItems.Checked = list.AllowEveryoneViewItems;

        //Disable the AllowRequest access checkbox if
        //the list is inheriting permissions as this
        //will be inherited as well
        if (list.Permissions.Inherited)
        {
            chkListAllowRequestAccess.Enabled = false;
        }
        else
        {
            chkListAllowRequestAccess.Enabled = true;
        }

        //Call the method that populates the “Field” listbox
        //with the fields(SPField) that are available in the selected
        //list
        GetListFields(list);
    }
}

//**************************************************
//This method populates the “Field” List box with
//the fields(SPField) that are available in the
//list(SPList) that is passed in
public void GetListFields(SPList list)
{
    //clear the list box before populating it
    //(the user may have selected a new list)
    lstFields.Items.Clear();

    //hide the field settings panel as
    //the user will need to select a new list
    pnlFieldSettings.Visible = false;

    //disable the update field button
    //as the user will need to select a new list
    btnUpdateField.Enabled = false;

    //iterate through each field(SPField) in the list(SPList)
    foreach (SPField field in list.Fields)
    {
        //Create a listItem for each field.
        //Set the “text” property to the title
        //and the value to the field ID
        //we will use the field ID to retrieve the
        //fields settings when the user selects it
        ListItem item = new ListItem(field.Title + ” [” + field.InternalName + “]”,         field.Id.ToString());
        lstFields.Items.Add(item);
    }
}

//*************************************************
// This method retrieves some of the field settings
// that are not accessible via the site or list settings
// pages on the SharePoint site
public void GetFieldSettings(object sender, System.EventArgs e)
{
    //Make the field settings panel visible
    //and enable the field settings button
    pnlFieldSettings.Visible = true;
    btnUpdateField.Enabled = true;

    //Get the ID of the selected list and
    //the ID of the field. We will use these
    //to retrieve the list and field settings
    Guid listGuid = new Guid(lstSiteLists.SelectedValue);
    Guid fieldGuid = new Guid(lstFields.SelectedValue);

    using (SPWeb site = SPContext.Current.Site.OpenWeb())
    {
        //get a reference to the list and field
        //from the list.
        SPList list = site.Lists[listGuid];
        SPField field = list.Fields[fieldGuid];

        //display the Field ID and internal name
        lblFieldID.Text = field.Id.ToString();
        lblFieldInternalName.Text = field.InternalName; 

        //check the CanToggleHidden Attribute of the field
        //and if false display a warning
        if (!(field.CanToggleHidden))
        {
            lblFieldWarning.Text = “Warning: The CanToggleHidden property of this field has been set to false; changing its \”hidden\” property could render your application unstable.”;
         }
         else
         {
             lblFieldWarning.Text = “”;
         }

        //retrieve the “hidden” property value
        //of the field and set the corresponding
        //checkbox
        chkFieldHidden.Checked = field.Hidden;
    }
}

//**************************************************
//This method updates the list settings according
//to the values specified in the form
public void UpdateList(object sender, System.EventArgs e)
{
    //Get the ID of the selected list
    Guid listGuid = new Guid(lstSiteLists.SelectedValue);
    using (SPWeb site = SPContext.Current.Site.OpenWeb())
    {
        SPList list = site.Lists[listGuid];
        list.AllowDeletion = chkListAllowDelete.Checked;
        if (!(list.Permissions.Inherited))
        {
            list.RequestAccessEnabled = chkListAllowRequestAccess.Checked;
        }
        list.Hidden = chkListHidden.Checked;
        list.AllowEveryoneViewItems = chkAllowEveryoneViewItems.Checked;

        list.Update();
        site.AllowUnsafeUpdates = false;
    }
}

public void UpdateField(object sender, System.EventArgs e)
{
    Guid listGuid = new Guid(lstSiteLists.SelectedValue);
    Guid fieldGuid = new Guid(lstFields.SelectedValue);

    using (SPWeb site = SPContext.Current.Site.OpenWeb())
    {
        SPList list = site.Lists[listGuid];
        SPField field = list.Fields[fieldGuid];

        lblFieldID.Text = field.Id.ToString();
        lblFieldInternalName.Text = field.InternalName;

        if (!(field.CanToggleHidden))
        {
            Type type = field.GetType();
            MethodInfo mi = type.GetMethod(“SetFieldBoolValue”, BindingFlags.NonPublic | BindingFlags.Instance);
            mi.Invoke(field, new object[] { “CanToggleHidden”, true });
        }

        field.Hidden = chkFieldHidden.Checked;
        field.Update();

    }
}

 

   

 

 

   

   

 

    Select List:

   
   

       
        List Settings

        ID:
       

        Base Template:
       

        Base Type:
       

       

       

        (must first turn off permission inheritance)

       

       
       
   

        Fields

       
   

       
        Field Settings

        ID:
       

        Internal Name:
       

       

       

       

       
       
   

    Advanced List Settings

    Advanced List Settings

Click here to download a zip file containing the Application Page.

 

Updated 8/26/2008: Changed how I obtained the reference to the SPWeb object throughout the code. The code was originally obtaining a reference to the SPWeb object via the current context from within a “using” statement. This was wrong as disposing of a shared resource such as an SPWeb object obtained from the current context may cause the SharePoint object model to behave unpredictably. Alternatively I could have removed the using statements and let SharePoint manage the object, but considering the number of lines of code it was easier to do a find and replace from “this.Web” to “SPContext.Current.Site.OpenWeb()” which does not return a reference to a shared resource. See Best Practices: Using Disposable Windows SharePoint Services Objects for more information on the subject.

Technorati Tags: SharePoint, WSS, MOSS, ASP, NET

Firefox Integrated Authentication and SharePoint

While I wouldn’t recommend Firefox as my browser of choice for any enterprise environment leveraging SharePoint, I do occasionally run into users that have it set as their default browser. The main complaint I hear over and over again, has to do with integrated authentication; the users having to enter their credentials whenever they browse a SharePoint site. This is NOT a SharePoint related issue, if an issue at all. There are certain settings in Firefox that must first be enabled for Integrated Authentication to work for a specific site.

Settings for NTLM:

  1. In the address bar type “about:config”
  2. In filter type “network.automatic”

  3. In the list, double-click “network.automatic-ntlm-auth.trusted-uris”
  4. Enter the URL for which you’d like to enable integrated Authentication. To enter multiple, separate them by commas.

  5. Click OK

Settings for Kerberos:

  1. In the address bar type “about:config”
  2. Search for the following settings and change their values accordingly

    • network.negotiate-auth.trusted-uris: Enter the URLs for which negotiate authentication should be done
    • network.negotiate-auth.delegation-uris: Enter the URLs for which delegation will be allowed
    • network.negotiate-auth.allow-proxies: Enables proxy authentication using the negotiate method
    • network.auth.use-sspi: Tells Firefox to use the Windows SSPI library

Technorati Tags: Kerberos, NTLM, Firefox, Authentication, SharePoint

Importing files into a SharePoint document library using regular expressions and WebDAV

Tim Jones has a fantastic post on the subject at http://simplyaprogrammer.com/2008/05/importing-files-into-sharepoint.html. I enjoyed the read and will likely need to do something similar in the feature.

Technorati Tags: sharepoint,wss,.net

Blog at WordPress.com.

Up ↑

%d bloggers like this: