After writing a PSI extension recently, Mike Shughrue and I learned the following lessons:
¾ Follow the deployment procedure – coding is easyJ, deploying a PSI extension requires multiple steps, follow each carefully. A good way to test if the web service is properly deployed is to type its address in IE and ensure it returns its definition.
¾ Locating DISCO.EXE – if you can’t find it under C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin; then install it using your Visual Studio DVD (under .NET Framework SDK -> Tools)
¾ Generating WSDL & DISCO files – if you get the following error when running DISCO.EXE under C:\Program Files\Microsoft Office Servers\12.0\WebServices\Shared\PSI:
The workaround is to create an IIS Virtual Directory under a site which is not managed by SharePoint Services V3, for instance “Test”, copy the ASMX in that directory and run this command instead:
Then copy the DISCO and WSDL files in the proper directory and follow the rest of the procedure to adapt the files to SharePoint V3.
¾ Automatically generate and deploy the DISCO and WSDL files – you could skip the steps above and use the following tool to automatically generate the two files and do the proper XML replacement: SharePoint Web Service DISCO and WSDL Generator
¾ Reading PSI configuration settings – Ideally the configuration settings such as database connection strings, impersonation parameters should not be hard coded in the C# for ease of deployment and maintenance. In our example the settings are defined in an application settings XML file (located under C:\Program Files\Microsoft Office Servers\12.0\WebServices\Shared\PSI) and the settings are set in the constructor of the WS. Another way to do it would be to store the settings in the web.config but he could not get it to work..
¾ Validate authorisation from all method call – to ensure that the EPM security is enforced each PSI calls validates the user using such algorithm:
private bool IsAuthorized(Guid userGuid)
bool isAuthorized = false;
Reporting.wsResource.ResourceAuthorizationDataSet resAuthDS = resource.ReadResourceAuthorization(userGuid);
foreach (Reporting.wsResource.ResourceAuthorizationDataSet.GroupMembershipsRow dr in resAuthDS.GroupMemberships.Rows)
secGrpDS = security.ReadGroup(dr.WSEC_GRP_UID);
if (secGrpDS.SecurityGroups.WSEC_GRP_NAME == SEC_GROUP)
isAuthorized = true;
// Eat the exception and return false.