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.

Advertisements

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.

Happy 2nd Anniversary, EndUserSharePoint.com!

Well, the point of this post is to say “Happy 2nd Anniversary EndUserSharePoint.com”. I really would like to congratulate Mark Miller ( founder ), Natasha Felshman, all the authors, commentors and contributors for the outstanding job they have been doing during the two past years. Needless to say, I am really proud to be a very small part of this wonderful community.

Just within a couple of years, the site has become a community of SharePoint authors who contribute their time and energy into providing some of the best content in the world for SharePoint Information Workers.

Guys there are very open-minded and they really care about the growth of the SharePoint community and this link proves it, Mark Miller was the first one to spread the word about my Arabic SharePoint screencasts. Didn’t I tell you ? I’m really proud to be a small part of such an amazing community:)

The statistics below reflect the huge success and impact of EndUserSharePoint on the SharePoint community, please join me in congratulating Mark Miller by leaving a comment here.

67

I would also like to extend a special thank you to all those who wished to meet me at SharePoint Conference 2009 by listing my name with all the SharePoint gurus and heroes, I’m really depressed that I won’t be able to make it but I’ll will be following the conference through the live media stream.

Usage Analysis is not capturing information for Web Application

Just thought of sharing this MSDN forum-thread with my blog followers since I have received this question more than once. Usage Analysis is really a common source of confusion among SharePoint administrators.

Q :

I have 3 Web Applications, webapp1, webapp2 and I recently added webapp3. each web application hosts about 5 site collections.
I have enabled usage analysis processing  on the farm level but it’s only capturing information for web app1 and web app2. And it’s not capturing any information for any site collection for web app3.

A :

Usage reporting from within MOSS runs on a daily schedule that is user configurable from the central administration, you must wait at least one day for any meaningful reporting to be available for new web application. By the way you should activate the reporting feature on all the site collections in the web application.

Q :

I have already activated the reporting feature on all the site collections and about 48 hours elapsed to collect the usage statistics.

A :

Run the following commands from the command prompt, wait for 24 hours and it should work.

stsadm -o setproperty -pn job-usage-analysis -pv no

stsadm -o setproperty -pn job-usage-analysis -pv yes


This sequence disables, then re-enables the job-usage-analysis job within SharePoint. It’s important to execute this sequence after adding new web applications.
Let me know after 24 hours.

Q :

Now the new web application usage info is captured.

A :

Note that when you add a new Web application to MOSS, usage analysis is not automatically reconfigured. In order to make usage analysis processing available for the new Web application, you must disable, then re-enable via central administration or through STSADM as I showed you.

“The specified network name is no longer available” Exception when using SharePoint Search API!

I ran into a very weird issue that caused me a real headache when using SharePoint Search API !
Below is the code I was using :

FullTextSqlQuery fts = new FullTextSqlQuery(site);
fts.QueryText = "SELECT AccountName FROM portal..scope()…";
fts.ResultTypes = ResultType.RelevantResults;
fts.RowLimit = 100;
ResultTableCollection rtc = fts.Execute();

 

When the last line executes, an exception is thrown with the following message :

The specified network name is no longer available. (Exception from HRESULT:
0x80070040), Exception Stack Trace :    at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(
Int32 errorCode, IntPtr errorInfo)     at Microsoft.Office.Server.Search.Query.FullTextSqlQuery.Execute()

I have also received the following error in the SharePoint Trace Logs:

10/05/2009 20:03:10.18 OWSTIMER.EXE (0x0850)                              0x08D0 Search Server Common                MS Search Administration                  0              High       Log Query:  More Information: The specified network name is no longer available.

Additionally, I have seen this error in the Windows Application log of the SharePoint web front end server:

Office Server Search EventID: 10038 Level: Error Query machine ‘<ServerName>’ has been taken out of rotation due to this error: The specified network name is no longer available. 0x80070040. It will be retried in 15 seconds.

Resolution:

This problem may occur because of an error in Windows Server 2008. If you use the TransactNamedPipefunction to request more than 8,000 bytes of data, Windows Server 2008 does not transfer the data correctly. To solve this issue, install the hotfix from KB 946487 on all Windows Server 2008 machines in the SharePoint farm, this will do the trick!

Hope this helps 🙂

Exporting ListViewWebParts!

ListViewWebPart cannot be exported by design, that’s true! ListViewWebPart elements are tied to the underlying list and views by GUID, and the GUID is unique for each view and each list in each site.

But what if you need to export it to add it to an AllUsersWebPart element in an onet.xml file ?

The following code snippet will export any web part (even if it is a ListViewWebPart ) from the page specified.

SPLimitedWebPartManager mgr = web.GetLimitedWebPartManager(

“default.aspx”

, System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);

foreach(WebPart webpart in mgr.WebParts )
{
          string Filename = @"c:\webparts\"+ webpart.ID + ".dwp";

System.Xml.XmlTextWriter writer =
new System.Xml.XmlTextWriter(Filename,Encoding.Default);

          webpart.ExportMode = System.Web.UI.WebControls.
                                    WebParts.WebPartExportMode.All;
          mgr.ExportWebPart(webpart, writer);
          writer.Close();
}