Creating mailing lists for SharePoint sites and blogs [No Code Required] – Part 3 : More Customizations to the subscription form using DataFormWebPart

NOTE : This article was published on EndUserSharePoint.com a couple of weeks ago and because of the wonderful feedback I received, I decided to cross-post it here too.

This is the third article in a multipart series that is intended to help you creating mailing lists for your SharePoint sites or blogs without writing a single line of .NET Code. In the introductory article, I have listed the project initiatives, requirements, and objectives. In Part 1, I created a secured backend where we will store the subscribers’ contacts. In Part 2, I have configured the ‘Contact’ content type, created a subscription form for the mailing list and did some simple customizations to it.

In this article, I will customize the subscription form I created in the previous article, utilize the magical DataFormWebPart to remove the unneeded columns, and change the form validation to be client sided rather than the default server-sided validation.

I will also show you how to validate the email addresses entered by the subscribers using regular expressions and, at the end, I will thrash out a trick to enable the DataFormWebPart to be viewed by anonymous users.

Let’s get started!

  1. In the Design view, click the default List Form Web Part to select it. From the Code View, put the cursor straight away before the ListFormWebPart and press enter.

8

 

2.  On the Insert menu, point to SharePoint Controls, and then click Custom List Form.

9

 

3. The List or Document Library Form dialog box opens up.

3.1. In the List or document library to use for form list, choose the list where we store our subscribers’ contacts.

3.2. In the Content type to use for form list, choose the ‘contact’ content type.

3.3. Under Type of form to create, click the ‘New item form’ as shown in the figure below.

10

 

3.4. The custom list form can comprise a toolbar to assist users in carrying out frequent actions for an item. The commands on the toolbar vary according to the type of the form. For example, the toolbar for the New Item Form looks like the following one.

11

As you can see, we do not need this toolbar in our subscription form so do not check the show standard toolbar checkbox.

4.  Now, the custom list form (Data Form Web Part) has been added to your subscription form. The custom list form shows the default fields for the selected form type, along with any default controls for each field. You can utilize the WYSIWYG tools in SharePoint Designer to add or eliminate columns, modify font formatting, or apply colors. When you do this, Extensible Stylesheet Language (XSL)  is directly inserted into the HTML. Although it is possible to amend the XSL directly in Code view, you can make use of the formatting tools in Design view to apply XSL without studying any XSL.

  1. 4.1. Remove all the unwanted fields from the form by removing the whole unwanted rows.

    4.2. Rename ‘Country/Region’ to be only ‘Country’.

    4.3. Change the font formatting, or apply the colors that go with your site’s theme.

    4.4. Remove the Ok and Cancel buttons at the top of the DataFormWebPart. We need them only once on our form.

12

As you can see the DataFormWebPart is incredibly cool. Within the XSL, you can input any HTML you want and, in effect, the sky is really the limit.

5. Now, you must hide the default List Form Web Part. Right-click the default List Form Web Part and then click Web Part Properties.

In the dialog box that appears, click the plus sign next to Layout, select the Hidden check box, and then click OK.

13

 

14

Note:  Do not delete the default List Form Web Part. This will break the page’s connection to the list.

6.  Next step is validating the users’ inputs. For instance, we need to make sure that the user has entered their e-mail address in a correct format since we are going to send them e-mails later.

6.1. Find the E-mail Address form field, right click on it in the designer, and click Show Common Control Tasks.

6.2. Change the “Format As” dropdown from “List Form Field” to “Text Box” as shown below.

15

 

6.3. Now drop a RegularExpressionValidator control from the asp.net controls toolbox beside the E-mail address text box as shown beneath.

16

 

17

 

6.4. Specify the RegularExpressionValidator control properties (such as ControlToValidate, ErrorMessage, Validate Expression) from the Tag Properties toolbar.

18

 

For ControlToValidate, choose the ID of the E-mail address field and for the ValidationExpression, choose Internet E-mail Address.

19

 

6.5. After specifying the control properties, you will end up with something like the following markup in the SharePoint Designer Code View.

20

That’s it! You now have custom client-sided validation on your form. You can also make use of the asp.net RequiredFieldValidator controls in the same way discussed in the previous step to make sure that the user has not left the text boxes empty.

7.     In addition, you can modify the markup of your form however you want. For instance, you can substitute the SharePoint:SaveButton control with a traditional asp.net button that calls some custom java script to do custom logic and save the item to the backend. I will leave this point to another discussion.

Didn’t I tell you? The DataFormWebPart is an incredibly wonderful creature.

For me, I have ended up with the one shown below.

21

 

8. Save your changes and navigate to the subscription form anonymously. You will receive an error message like the one shown below.

22

9 . I have blogged about this error on my blog a couple of weeks ago. For now, just set DataSourceMode of SPDataSource control to Webs or ListOfLists. This will permit anonymous users to view the DataFormWebPart that holds the subscription form fields

23

10. Congratulations! You are now ready to preview the page in the browser.

24

Summary

One of the initiatives of this series of articles is to show you how powerful and flexible the Data Form Web Part is. In this article, we have only scratched the surface; there are still a lot of cool and nifty features when it comes to the magical Data Form Web Part. Laura Rogers has really done a great job discussing and discovering wonderful features in the Data Form Web Part. I would advise you to have a look at her articlesat EndUserSharePoint.com for more tips and tricks.

In my next article I will go into some completely new stuff when we explore SharePoint Designer Workflows. I will create a workflow that sends welcome e-mails to the list subscribers as soon as their requests to join the list are approved. And as we agreed in the introductory part, I will not write a single line of code.

 

About EndUserSharePoint:

EndUserSharePoint.com is a community of SharePoint authors dedicated to providing content to SharePoint End Users on three levels: Information Worker, Power User/Site Administrator and Site Collection Administrator.

 

Creating Folders using Modules

Sometimes, you will find yourself in a situation that you not only provision pages to SharePoint content database, but also you need to create folder in which those pages will be provisioned.

Consider the following example :

 <File Url="MyPagesFolder/MyPage.aspx" />

This way, you can use the URL attribute of the file element to create folders in your site. SharePoint will create the folder “MyPagesFolder”  if it doesn’t exist. You can do this trick either within the URL attribute of the Module element or the file element.

Another point to consider in the previous example is that I omitted the Path attribute which makes the URL attribute acts as both (URL and path), so now SharePoint will get files from MyPagesFolder relative to the feature folder, then it will create a folder called MyPagesFolder and provision MyPage.aspx to it.

More robust usage of OpenWeb()

1:  using(SPSite site = new Site(http://www.portal.com)) 
   2:  {    
   3:      SPWeb web = site.OpenWeb("/anotherWeb/"); // no exception
   4:   
   5:      string title = web.Title;  // throws exception
   6:  }

 

The first line in the using clause will not throw an exception even if anotherWeb doesn’t exist , but you’ll encounter a FileNotFoundException exception in the second line since web is a null reference.

To make your code more robust, you should check the existence of the web before using it as follows:

   1:  using(SPWeb web = site.OpenWeb("/anotherWeb/"))
   2:  {
   3:     if(web.Exists)
   4:     {
   5:         string title = web.Title;
   6:     }
   7:  }

Alternatively, The SPSite.OpenWeb method has a (string, bool) overload. If you set the bool to true you should get an exception if the site doesn’t exist. Waldek Mastykarz has explained this behavior on his blog @http://blog.mastykarz.nl/inconvenient-opening-spsite-openweb.

Arabic Screencasts for “SharePoint Pages” by Osama Mourad

I have been working lately with Osama Mourad ( Development Manager at LINKdotNET ) on putting together a series of screencasts in Arabic for SharePoint4Arabs.com. Osama has just sent me a note notifying me that he is done with his first screencast titled “SharePoint Pages”.

I’m really happy to be presenting this , It’s really informative and useful. Thanks, Osama. Your work is appreciated.

Differences between Ghostable and GhostableInlibrary

A common source of confusion is is the Type attribute of the file element used when creating a module to provision files in SharePoint database.

You can set this attribute to Ghostable or GhostableInLibrary or you can leave it alone and not to set it meaning that it’s “Unghostable“.

Ghostable and GhostableInLibrary –> Specifies that the file be cached in memory on the WFE. Both values specify that the file be cached, but GhostableInLibrary specifies that the file be cached as part of a list whose base type is Document Library and that you can work with the file as you would with any other file in the library ( check-in, check-out, version history).

When changes are made, for example, to the home page through the UI, only the differences from the original page definition are stored in the database, while default.aspx is cached in memory along with the schema files. The HTML page that is displayed in the browser is constructed through the combined definition resulting from the original definition cached in memory and from changes stored in the database.

If you don’t set a value this means that the file is Unghostable implying that the file will not be cached in memory in WFE and that it’ll be completely stored in the database.

Managing Property Bags through SharePoint Designer!

Continuing our discussion about “Property Bag”, I have recently discovered that end users can manipulate their SharePoint sites property bags through SharePoint Designer 2007.

To view the property bag.  Go to Site -> Site Settings.  Then click on the Parameters tab.  On this tab, you will be able to see the values of all of your custom property bag values.

63

62

Retrieving the SSP Database connection string using Reflection!

I’m currently working on a project in which it’s required to dynamically retrieve the Connection String of a Web Application’s Shared Services database. Unfortunately, this is not easily accessible via the object model as the desired properties are internal.

The task was tricky and it took me sometime to figure out how to accomplish it and the only solution was “Reflection”!

Below is the method I have came up with:

public static string GetSSPConnectionString(SPWebApplication webApp)
{
    try
    {
        ServerContext serverContext = ServerContext.GetContext(webApp);

        Type serverContextType = serverContext.GetType();
        // Get the value of the field m_ServerFarm;                
        SPPersistedObject serverFarm = (SPPersistedObject)serverContextType.
        GetField("m_ServerFarm", BindingFlags.Instance | BindingFlags.NonPublic).
        GetValue(serverContext);
        // Now we need to retrieve a collection of all the Shared Services Providers
        // public SharedResourceProviderCollection SharedResourceProviders { get; }
        PropertyInfo sharedSerivesProvidersProperty = serverFarm.GetType().
        GetProperty("SharedResourceProviders");
        IEnumerable sharedServicesProviders = (IEnumerable)
        sharedSerivesProvidersProperty.GetValue(serverFarm, null);

        Type sharedServiceProviderType = Assembly.GetAssembly(serverContextType).
        GetType("Microsoft.Office.Server.Administration.SharedResourceProvider");
        PropertyInfo webApplicationsProperty = sharedServiceProviderType.
        GetProperty("WebApplications");

        object serviceDB=null;
        foreach (SPPersistedObject sharedSericeProvider in sharedServicesProviders)
        {
            IEnumerable webApplications = (IEnumerable)webApplicationsProperty.
            GetValue(sharedSericeProvider, null);
            // Iterate through all the web applications associated with the current SSP.
            foreach (SPWebApplication webAppAssociatedWithSSP in webApplications)
            {
                if (webApp.Id == webAppAssociatedWithSSP.Id)
                {
                    serviceDB = sharedSericeProvider.GetType().GetProperty
                    ("ServiceDatabase").GetValue(sharedSericeProvider, null);
                    return ((Microsoft.SharePoint.Administration.SPDatabas(serviceDB)).
                    DatabaseConnectionString);                
                }
            }                    
        }
        return String.Empty;                  
    }
    catch (Exception ex)
    {
        ReportsLogger.GetInstance().LogException(ex);
        return String.Empty;
    }
    finally
    {
        ReportsLogger.GetInstance().Debug("Exiting method");
    }

}

 

You can also download the method above from here.

Storing Metadata related to a site collection

For those of you that are not familiar with the Property Bag concept, it is a place to store metadata or properties for your SharePoint objects. However, when exploring the SharePoint object model, I have noticed that SPWeb provides a Property bag to store metadata info related to a web site, where SPSite doesn’t. So the only way to store metadata info related to a site collection (SPSite) is to use the property bag of the root web.

SPSite  Represents a collection of sites on a virtual server, including a top-level site and all its subsites.
SPWeb 
Represents a Windows SharePoint Services Web site.

To store a property in the bag :

SPPropertyBag Bag =  site.RootWeb.Properties;
if (!Bag.ContainsKey("PropertyName"))
{            
      Bag.Add("PropertyName", "PropertyValue");
      Bag.Update();
}

And to remove a property, use the following snippet :

SPPropertyBag Bag =  site.RootWeb.Properties;
if (Bag.ContainsKey("PropertyName"))
{
    Bag["PropertyName"]=null;                            
    Bag.Update();
}

For more SharePoint code snippets, I would recommend SPCodeSnippets available at codeplex.

Creating mailing lists for SharePoint sites and blogs [No Code Required] – Part 2: Creating a custom subscription form

NOTE : This article was published on EndUserSharePoint.com a couple of weeks ago and because of the wonderful feedback I received, I decided to cross-post it here too.

This is the second article in a multipart series that is intended to help you create mailing lists for your SharePoint sites or blogs without writing a single line of .NET Code. In the introductory article, I listed the project initiatives, requirements, and objectives. In Part 1, I created a secured backend where we store the subscribers’ contacts. In this article, we will continue our journey, let’s carry on!

In the previous article, I made use of the ‘Contacts list template, provided out-of-the-box by SharePoint, to create a list which will act as the backend for our mailing list. In this article, I will show you how to configure the ‘Contact’ content type, create a custom subscription form and do some sort of customization. The intention of these customizations is not only to make the subscription form look different from the out-of-the-box list forms but also to show you the power, simplicity, and efficiency of SharePoint Designer 2007.

  1. Navigate to the list settings page > Advanced settings.

69

2. Make sure that management of content types is turned on

70

3. Navigate to the contact content type settings page from the list settings as shown underneath:

71

4. Configure the content type fields from the content type settings page. We need a  list subscriber to mandatorily supply their first namelast name and e-mail address and optionally supply theirCompanyCity and Country.

72

73

5. Now, navigate to the New Form (NewForm.aspx) by adding a new contact to the list as follows :

74

75

6.As shown in the figure above we need to get rid of the highlighted areas. I will show you in this article, and the next one how, to accomplish that.

7. Open up SharePoint Designer, connect to your SharePoint site collection, and supply your credentials.

8.Choose the list that we created in the previous article from the folder list. If the Folder List is not visible, on the View menu, click Folder List.

9.Make a copy from the NewForm.aspx and rename the copied version from NewForm_copy(1).aspx to subscribe.aspx as follows:

76

77

78

10. Change the list New item form from NewForm.aspx to subscribe.aspx using the supporting files tab of the list properties’ dialogue box as illustrated below:

80

81

82

11.Now choosing to add a new contact to the list will redirect you to subscribe.aspx rather than NewForm.aspx.

12.Our next task is to modify the newly created form (subscribe.aspx) to look like a mailing list subscription form rather than the traditional SharePoint list forms.

13.Open subscribe.aspx using SharePoint designer.

14.Select “New Item” highlighted in the figure below. Delete it with the colon preceding it.

83

15.    Now, we need to eliminate the “New Item” from the form breadcrumb.

15.1. Select the “PlaceHolderTitleBreadcrumb” placeholder from the Master Page toolbar as shown in the figure below.

84

 

Note:  You can show this toolbar if it is hidden from View menu > Toolbars.

15.2. The word (Master) on the content placeholder tab means that the content is retrieved from the master page. To make this content region editable to override the retrieved data, click the arrow in the upper-right corner to show the Common Content Tasks list, and then click Create Custom Content as shown in the figure below. This will automatically create a new content region that will fill the placeholder in this page rather than using the Master’s default content.

85

 

15.3. Replace the SiteMapPath control with a link to the site collection’s welcome page. You can use the handy “SPLinkButton” control in conjunction with “ProjectProperty” control to accomplish that as shown below. The  good thing about SPLinkButton is that it is aware of ~site and ~sitecollection expression tokens.

 

1

2

 

16. To change the page title “IE Tab title”, locate the ”PlaceHolderPageTitle” placeholder using the Master Page toolbar discussed above and replace the ListFormPageTitle control with your own title.

3

 

4

 

17 . Now, we are in a good shape; only one non-compulsory step is left which is adding the left navigation bar back to the page. Note the word (Custom) on the content placeholder tab. This means that the content is custom content for this page only, and that it is not retrieved from the attached master page. Nevertheless, we do not need any custom content for this page. We need to retrieve the left navigation menu from the master page so the only thing we need to do is defaulting the region to the master’s content using the Common Content Tasks as shown in the figure below.

5

 

18.  Save your changes by clicking Save on the File menu. A message appears warning you that saving your changes will customize a page from the site definition. Click Yes.

6

 

19. And here is what you will end up with, if you follow the preceding steps.

7

 

Note: If you are not pleased with the customizations that you have made to the page, you can always reset it to the site definition.

Summary:

In this article, I showed you how to configure the ‘Contact’ list content type, create a subscription form for the mailing list, make it the default New Item Form and do some simple customizations to it.

In the next article, I will show you how to customize the form fields, use the extremely powerful DataFormWebPart, change the form validation mechanism to be client sided, add your own validation logic, configure the SPDataSource control and much more ..

About EndUserSharePoint:

EndUserSharePoint.com is a community of SharePoint authors dedicated to providing content to SharePoint End Users on three levels: Information Worker, Power User/Site Administrator and Site Collection Administrator.