How to: Create a Proxy Assembly for WCF Services
Published: May 2010
In developing applications for Microsoft Project Server 2010, setting a reference to a Windows Communication Foundation (WCF) service in the Project Server Interface (PSI) can be done by using a proxy assembly or a proxy source code file. The Project 2010 SDK download includes the PSI proxy source code for WCF services in the Service pack 1 (SP1) version of Project Server 2010. This article shows how to create a PSI proxy assembly and update the proxy assembly source code files for future Project Server service packs or updates.
There are no object model changes in the PSI for SP1, so the proxy files in the Project 2010 SDK download are the same as in previous releases of the SDK. After installing SP1, you do not need to generate new PSI proxy files with the GenWCFProxyAssembly.cmd script, as described in the Updating the PSI Proxy Source Files section of this article.
This article includes the following sections:
Use a test installation of Project Server 2010.
The procedure in this article for updating the PSI proxy source files require temporarily changing the web.config file for the Project Server Shared Service application. These procedures should be done only on a test installation of Project Server 2010.
The Prerequisites for WCF-Based Code Samples article includes the procedure to build a PSI proxy assembly by using the source files in the Project 2010 SDK download, along with other information about creating a WCF-based application that uses the PSI. For releases of Project Server 2010 through SP1, you do not need to update the PSI proxy source files that are in the Project 2010 download.
For a link to the Project 2010 SDK download, see the Project Developer Center. When you install the SDK download, the Documentation\Intellisense\WCF folder contains the proxy source files for the WCF interface of the PSI services in the Source.zip file. You can extract the source files, and then use the CompileWCFProxyAssembly.cmd script to compile the ProjectServerServices.dll proxy assembly.
You can update the PSI proxy source files and build a new ProjectServerServices.dll proxy assembly for all WCF services in the PSI, by using the GenWCFProxyAssembly.cmd script in the Documentation\Intellisense\WCF folder of the Project 2010 SDK download. However, before using the GenWCFProxyAssembly.cmd script, you must temporarily modify the web.config file for Project Web App, as described in the following procedure.
If you use the GenASMXProxyAssembly.cmd script in the Documentation\Intellisense\WSDL folder to generate the ProjectServerServices.dll proxy assembly, it does not work for WCF-based applications. The GenASMXProxyAssembly.cmd script calls wsdl.exe, which generates source code files for the ASMX Web services.
The ASMX-based proxy assembly does not include the necessary attributes, the channel interface, or the client class for each PSI service. For example, the Resource WCF service includes the ResourceChannel interface and the ResourceClient class, which the Resource ASMX Web service does not include.
The GenWCFProxyAssembly.cmd script generates output files for the WCF services in the PSI, and then compiles the assembly. To run the script on a test installation of Project Server, do the following:
Make a copy of the web.config file for the back-end Project Service application in [Program Files]\Microsoft Office Servers\14.0\WebServices\Shared\ProjectServer\PSI.
Copy the web.config.RTM_4RefOnly.txt file from the Documentation\Intellisense\web.config.files subdirectory in the Project 2010 SDK download to the back-end Project Service application directory, and then rename the file as web.config.
In a Command Prompt window, run iisreset.
Run GenWCFProxyAssembly.cmd. After you run the script, restore the original web.config file.
Run iisreset again.
Changes in Claims Authentication, Service Bindings, and EndPoints
In the Project Server 2010 beta version, claims-based authentication used encryption with Secure Subscriber Line (SSL) stream security. However, the encryption required too much overhead for each call to the server.
In the released version, claims-based authentication uses custom bindings named ClaimsHttpFast and ClaimsHttpSecurity, which do not use encryption or the HTTPS security binding. The custom binding greatly improves throughput for messages that are signed. However, the Metadata Exchange (MEX) endpoints in the Project Server service application and other service applications in Microsoft SharePoint Server 2010 do not use signed messages. Therefore, when you try to set a reference to a back-end service, or use a browser URL such as http://localhost:32843/1712e91aeb884cdfb437299b89de3443/psi/project.svc, the message is blocked. The service returns the following error:
The service encountered an error. An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is: System.InvalidOperationException: An exception was thrown in a call to a policy export extension. Extension: System.ServiceModel.Channels.TransportSecurityBindingElement Error: Security policy export failed.
In the released version of Project Server 2010, service endpoints defined in the web.config file use the custom bindings. For example, the following binding and endpoint for the Project service results in an InvalidOperationException error when you try to set a service reference.
<customBinding> <binding name="ClaimsHttpFast"> <security authenticationMode="IssuedTokenOverTransport" allowInsecureTransport="true" /> . . . </binding> </customBinding> . . . <service name="Microsoft.Office.Project.Server.Wcf.Implementation.ProjectImpl" behaviorConfiguration="ProjectServerBehavior" > . . . <endpoint address="" binding="customBinding" behaviorConfiguration="ProjectServerEndpointBehavior" bindingConfiguration="ClaimsHttpFast" contract="Microsoft.Office.Project.Server.Interfaces.IProject" /> <endpoint </service>
Using the Temporary Web.config File
In the web.config.RTM_4RefOnly.txt file, services use the ClaimsHttpSecurity and ClaimsHttpFast children of the basicHttpBinding element. The entire customBinding element is commented out. Each of the service endpoints uses the basicHttpBinding element, rather than the customBinding element. Those changes enable Visual Studio to directly set a service reference without an error.
Following is the complete bindings element in the web.config.RTM_4RefOnly.txt file:
<bindings> <basicHttpBinding> <binding name="mexHttpBinding"> <security mode="None"> </security> </binding> <binding name="ClaimsHttpSecurity"> <security mode="None" > </security> </binding> <binding name="ClaimsHttpFast"> <security mode="None"> </security> </binding> </basicHttpBinding> </bindings>
Following is the complete service element for the Project service. The endpoints for ClaimsHttpSecurity and ClaimsHttpFast use the basicHttpBinding element, instead of the customBinding element.
<service name="Microsoft.Office.Project.Server.Wcf.Implementation.ProjectImpl" behaviorConfiguration="ProjectServerBehavior" > <endpoint address="secure" binding="basicHttpBinding" bindingConfiguration="ClaimsHttpSecurity" behaviorConfiguration="ProjectServerEndpointBehavior" contract="Microsoft.Office.Project.Server.Interfaces.IProject" /> <endpoint address="" binding="basicHttpBinding" behaviorConfiguration="ProjectServerEndpointBehavior" bindingConfiguration="ClaimsHttpFast" contract="Microsoft.Office.Project.Server.Interfaces.IProject" /> <endpoint address="mex" binding="basicHttpBinding" bindingConfiguration="mexHttpBinding" name="mex" contract="IMetadataExchange" /> </service>
Although you could use the preceding discussion to create a temporary web.config file for the back-end Project Service application, manual editing can introduce errors. The binding definitions for both of the claims endpoints must be changed for every service. We recommend that you copy the web.config.RTM_4RefOnly.txt file in the SDK download and use it for the temporary web.config file.
Using the GenWCFProxyAssembly.cmd Script
Following is the GenWCFProxyAssembly.cmd script, as in the Documentation\Intellisense\WCF folder of the SDK download. You can use wsdl.exe from any location; they are the same versions.
Before using the script, change the GUID name of the Project Server Service application directory.
@echo off @ECHO ------------------------------------------------------ @ECHO Creating the C# files for the WCF-based proxy assembly @ECHO ------------------------------------------------------ REM ** Replace ServerName with the name of the server and REM the instance name of Project Web App. Do not use localhost. (set VDIR1=http://ServerName/ProjectServerName/_vti_bin/PSI) REM ** Replace the GUID for your Project Server Service virtual directory name. ** (set VDIR2=http://localhost:32843/1712e91aeb884cdfb437299b89de3443/PSI) (set OUTDIR=.\Source) REM ** Wsdl.exe is the same version in the v6.0A and v7.0A subdirectories. (set WSDL="C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bin\x64\wsdl.exe") if not exist %OUTDIR% ( md %OUTDIR% ) REM Use the back-end Project Service application URL for the WCF services. REM ** The following command is all on one line. for /F %%i in (Classlist_WCF.txt) do svcutil.exe /tcv:Version35 /serializer:XmlSerializer /nologo /t:code /l:CS /n:*,WebSvc%%i /d:.\Source /o:wcf.%%i.cs %VDIR2%/%%i.svc REM Use the front-end Project Web App URL for the LoginForms and LoginWindows services. %WSDL% /nologo /l:CS /namespace:WebSvcLoginForms /out:%OUTDIR%\wsdl.LoginForms.cs %VDIR1%/LoginForms.asmx %WSDL% /nologo /l:CS /namespace:WebSvcLoginWindows /out:%OUTDIR%\wsdl.LoginWindows.cs %VDIR1%/LoginWindows.asmx @ECHO ---------------------------- @ECHO Compiling the proxy assembly @ECHO ---------------------------- (set SOURCE=%OUTDIR%\) (set CSC=%WINDIR%\Microsoft.NET\Framework\v3.5\csc.exe) (set ASSEMBLY_NAME=ProjectServerServices.dll) %CSC% /t:library /out:%ASSEMBLY_NAME% %SOURCE%*.cs
The script uses the Classlist_wcf.txt file, which contains the list of PSI services that are available for third-party developers.
Admin Archive Calendar CubeAdmin CustomFields Driver Events LookupTable Notifications ObjectLinkProvider PortfolioAnalyses Project QueueSystem ResourcePlan Resource Security Statusing TimeSheet Workflow WssInterop
The arbitrary namespaces created for both the ASMX Web services and the WCF services are the same, so that the ProjectServerServices.xml file for Intellisense works with either version. For example, the namespace of the Resource service in the WCF-based proxy assembly and in the ASMX-based proxy assembly is SvcResource. You can, of course, change the namespace name in the \n parameter for the SvcUtil.exe command in the GenWCFProxyAssembly.cmd script—if you ensure that the names match in the proxy assembly and in the ProjectServerServices.xml file.