Prerequisites for ASMX-Based Code Samples

Applies to: Office 2010 | Project 2010 | Project Server 2010 | SharePoint Server 2010

In this article
Setting Up the Development Environment
Creating the Application and Adding a Web Service Reference
Setting Other References
Using Claims Multi-Authentication
Changing the Values of Generic Constants
Verifying the Results
Cleaning Up

Many of the code samples included in the Class Library and Web Service Reference conform to a standard format developed for the Microsoft Office Project 2007 SDK that uses ASMX Web services. The samples are designed to be copied into a console application and run as a complete unit. Exceptions are noted in the sample.

New samples in the Project 2010 SDK conform to a format that uses Windows Communication Foundation (WCF) services. The ASMX-based samples can also be adapted to use WCF services. This article shows how to use the samples with ASMX Web services. For information about using the samples with WCF services, see Prerequisites for WCF-Based Code Samples.

Note

New applications should use the WCF interface, which is the Microsoft recommended technology for network communications. Existing applications that use the ASMX interface can use the URL only through Project Web App, which checks Project Server permissions.

The URL through the back-end SharePoint Web Services application is used for applications and middleware components that run only on the Project Server computer and for applications that use impersonation. The ASMX interface is not available through the back-end URL. For more information about the ASMX interface and the WCF interface, see Overview of WCF and the PSI.

Before running the code samples, you must set up the development environment, configure the application, and change generic constant values to match your environment. This article includes the following sections:

  • Setting Up the Development Environment

  • Creating the Application and Adding a Web Service Reference

    • Building a PSI Proxy Assembly

    • Adding a PSI Proxy File

    • Adding a Web Service Reference

  • Setting Other References

  • Using Claims Multi-Authentication

  • Changing the Values of Generic Constants

  • Verifying the Results

  • Cleaning Up

Setting Up the Development Environment

  1. Set up a test Project Server system.

    Use a test Project Server system whenever you are developing or testing. Even when your code works perfectly, interproject dependencies, reporting, or other environmental factors can cause unintended consequences.

    Note

    Ensure that you are a valid user on the server, and check that you have sufficient permissions for the Project Server Interface (PSI) calls that your application uses.

    In some cases, you may need to do remote debugging on the server. You may also need to set up an event handler by installing an event handler assembly on the Project Server computer, and then configuring the event handler by using the Server Settings page in Project Web App.

  2. Set up a development computer.

    You usually access the PSI through a network. The code samples are designed to be run on a client separate from the server, except where noted.

    1. Install the correct version of Microsoft Visual Studio.   Except where noted, the code samples are written in Microsoft Visual C#. They can be used with Microsoft Visual Studio 2008 SP1 or Microsoft Visual Studio 2010.

      Note

      You can use Visual Studio 2008 for most applications developed for Project Server 2010. Project Server workflow applications require you to develop on the Project Server computer, by using Visual Studio 2010. We recommend Visual Studio 2010 for all Project Server development.

    2. Copy Project Server DLLs to the development computer.   For non-workflow applications, copy the following assemblies from [Program Files]\Microsoft Office Servers\14.0\Bin on the Project Server computer to the development computer:

      • Microsoft.Office.Project.Server.Events.Receivers.dll

      • Microsoft.Office.Project.Server.Library.dll

  3. To use Intellisense descriptions for classes and members in Project Server assemblies, copy the updated Intellisense XML files from the Project 2010 SDK download to the same directory where the Project Server assembly is located. For example, copy the Microsoft.Office.Project.Server.Library.xml file to the directory where your application will set a reference to the Microsoft.Office.Project.Server.Library.dll assembly.

    Intellisense descriptions for the PSI Web services require that you create a PSI proxy assembly by using the script in the Intellisense\WSDL subdirectory in the Project 2010 SDK download. The script creates the ASMX-based ProjectServerServices.dll proxy assembly. For more information, see the [ReadMe_Intellisense].mht file in the SDK download.

Creating the Application and Adding a Web Service Reference

  1. Create a console application.

    When you create a console application, in the drop-down list of the New Project dialog box, select .NET Framework 3.5. You can copy the PSI example code into the new application.

  2. On the .NET tab of the Add Reference dialog box, add a reference to System.Web.Services.

  3. Copy the code.

    Copy the complete code example into the Program.cs file of the console application.

  4. Set the namespace for the sample application.

    You can either change the namespace listed at the top of the sample to the application default namespace, or change the default application namespace to match the sample. You can find the default application namespace in the application properties.

    For example, the code sample for CreateNewAssignment has the namespace Microsoft.SDK.Project.Samples.CreateNewAssignment. Copy the namespace from the Program.cs file and then open the project Properties pane (on the Project menu, click CreateNewAssignment Properties). On the Application tab, copy the namespace into the Default namespace text box.

  5. Set the Web references.

    Many examples require a reference to one or more of the PSI Web services. These are listed in the sample itself or in comments that precede the sample. To get the correct namespace of the Web references, ensure that you first set the default application namespace.

    There are three ways to add an ASMX Web service reference:

    • Build a PSI proxy assembly and set a reference to the assembly. See Building a PSI Proxy Assembly.

    • Add a proxy file from the wsdl.exe output to the Visual Studio solution. See Adding a PSI Proxy File.

    • Add a Web service reference by using Visual Studio. See Adding a Web Service Reference.

Building a PSI Proxy Assembly

You can build and use the ProjectServerServices.dll proxy assembly for all ASMX-based Web services in the PSI, by using the GenASMXProxyAssembly.cmd script in the Documentation\Intellisense\WSDL folder of the Project 2010 SDK download. For a link to the download, see Project 2010 SDK Documentation.

Note

There are no object model changes in the PSI for the Service Pack 1 (SP1) version of Project Server 2010, 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 source files with the GenWCFProxyAssembly.cmd script. Instead, you can extract the proxy source files from the Source.zip file, and then use the CompileASMXProxyAssembly.cmd script to compile the ASMX-based ProjectServerServices.dll.

If you use the GenWCFProxyAssembly.cmd script in the Documentation\Intellisense\WCF folder, it does not work for ASMX-based applications. The script calls SvcUtil.exe, which generates source code files for the WCF services. The WCF proxy files include different attributes, the channel interface, and a client class for each PSI service. For example, the Resource WCF service includes the ResourceChannel interface, the Resource interface, and the ResourceClient class that implements Resource, which the Resource ASMX Web service does not include.

Following is the GenASMXProxyAssembly.cmd script that generates WSDL output files for the PSI Web services, and then compiles the assembly. You can use wsdl.exe from any location; they are the same versions.

	@echo off
    @ECHO ---------------------------------------------------
    @ECHO Creating C# files for the ASMX-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 VDIR=https://ServerName/pwa/_vti_bin/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 Project Web App URL for the Web services.
    
    for /F %%i in (Classlist_asmx.txt) do %WSDL% /nologo /l:CS /namespace:Svc%%i /out:%OUTDIR%\wsdl.%%i.cs %VDIR%/%%i.asmx?wsdl 
    
    @ECHO ----------------------------
    @ECHO Compiling the proxy assembly
    @ECHO ----------------------------
    
    (set SOURCE=%OUTDIR%\wsdl)
    (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_asmx.txt file, which contains the list of Web services that are available for third-party developers.

Admin
Archive
Calendar
CubeAdmin
CustomFields
Driver
Events
LoginForms
LoginWindows
LookupTable
Notifications
ObjectLinkProvider
PortfolioAnalyses
Project
QueueSystem
ResourcePlan
Resource
Security
Statusing
TimeSheet
Workflow
WssInterop

The arbitrary namespaces created by the scripts for both the ASMX Web services and the WCF services are the same, so that the Intellisense file works with either assembly. 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 names—if you ensure that they match in the proxy assembly and in the ProjectServerServices.xml Intellisense file.

If a code sample in the SDK uses a different name for a PSI Web service namespace, for example ProjectWebSvc, you must change the sample to use SvcProject to match the names in the proxy assembly.

An advantage to using the ASMX-based proxy assembly is that it includes all PSI Web service namespaces; you do not need to create multiple Web references. Another advantage is that, if you add the ProjectServerServices.xml file to the same directory where you set a reference to the ProjectServerServices.dll proxy assembly, you can also get Intellisense descriptions for the PSI classes and members. For more information, see the [ReadMe_Intellisense].mht file in the Intellisense folder of the SDK download.

A disadvantage to using the proxy assembly is that the solution is large and you must distribute and install the proxy assembly with the solution. You must also use the same namespaces that are in the proxy assembly and Intellisense files, unless you change the script and ProjectServerServices.xml Intellisense file to use different namespaces.

Adding a PSI Proxy File

Adding a proxy file from WSDL output:   Instead of setting a reference to the proxy assembly, you can add one or more of the WSDL output files to a Visual Studio solution. For example, after running the GenASMXProxyAssembly.cmd script, add the wsdl.Project.cs file to a Visual Studio solution. Instead of running the script, you can run the following commands to generate a single source file, for example:

    set VDIR=https://ServerName/ProjectServerName/_vti_bin/psi
    set WSDL="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\x64\wsdl.exe"
    %WSDL% /nologo /l:cs /namespace:SvcProject /out:wsdl.Project.cs %VDIR%/Project.asmx?wsdl

To define a Project object as a class variable named project, use the following code. The AddContextInfo method adds the context information to the project object for Windows logon and Forms-based logon

private static SvcProject.Project project;
private static SvcLoginForms.LoginForms loginForms =
            new SvcLoginForms.LoginForms();
. . .
public void AddContextInfo()
{
    // Add the Url property.
    project.Url = "https://ServerName/ProjectServerName/_vti_bin/psi/project.asmx";

    // Add Windows credentials.
    project.Credentials = CredentialCache.DefaultCredentials;

    // If Forms authentication is used, add the Project Server 
    // cookie for a successful Forms user logon.
    
    project.CookieContainer = loginForms.CookieContainer;
}

Adding a Web Service Reference

If you do not use the ASMX-based proxy assembly or add a WSDL output file, you must set one or more individual Web references. The following steps show how to set a Web reference by using Visual Studio 2010:

  1. In Solution Explorer, right-click the References folder, and then click Add Service Reference.

  2. In the Add Service Reference dialog box, click Advanced.

  3. In the Service Reference Settings dialog box, click Add Web Reference.

  4. In the URL text box, type https://ServerName/ProjectServerName/_vti_bin/psi/ServiceName.asmx?wsdl, and then press Enter. If you have Secure Sockets Layer (SSL) installed, you should use the HTTPS protocol instead of the HTTP protocol. Replace ServerName with the name of the server that you are using. Replace ProjectServerName with the virtual directory name of your Project Server site, such as PWA. Replace ServiceName with the name of the Web service, such as Project.

    OR

    Open your Web browser, and navigate to https://ServerName/ProjectServerName/_vti_bin/psi/ServiceName.asmx?wsdl (substitute HTTPS for HTTP, if necessary). Save the file to a local directory, such as C:\Project\WebServices\ServiceName.wsdl. In the Add Web Reference dialog box, for URL, type the file protocol and the path to the file. For example, type file://C:\Project\WebServices\Project.wsdl.

    The previous URL is the standard URL for Project Server Web services.

  5. After the reference resolves, type the reference name in the Web reference name text box. Code examples in the Project 2010 SDK use the arbitrary standard reference name ServiceNameWebSvc. For example, the Project Web service is named ProjectWebSvc.

For application components that must run on the Project Server computer, use impersonation, or have elevated permissions, use a WCF service reference instead of an ASMX Web reference. For more information, see Prerequisites for WCF-Based Code Samples.

Setting Other References

Project Server applications often use other services, such as Microsoft SharePoint Foundation 2010 Web Services. If other services are required, they are noted in the example.

Local references for the code sample are listed in using statements at the top of the sample:

  1. In Solution Explorer, right-click the References folder, and then click Add Reference.

  2. Click Browse, and then browse to the location where you stored the Project Server DLLs that you copied previously. Choose the DLLs you need, and then click OK.

Note

Ensure that the assembly versions on your development computer exactly match those on the target Project Server computer.

Using Claims Multi-Authentication

Authentication of Project Server users, whether by Windows authentication or Forms authentication, is done through claims processing in Microsoft SharePoint Foundation 2010. Multi-authentication means that the Web application on which Project Web App is provisioned supports both Windows authentication and Forms-based authentication. If that is the case, a call to a WCF or ASMX service that uses Windows authentication will fail with the following error, because the claims process cannot determine which type of user to authenticate:

The server was unable to process the request due to an internal error. 
. . .

To fix the problem for ASMX, all calls to PSI methods should be to a derived class that is defined for each PSI Web service. The derived class must also use the SvcLoginWindows.LoginWindows class to get a cookie for the derived PSI service class. In the following example, the ProjectDerived class derives from the SvcProject.Project class. The derived class adds the EnforceWindowsAuth property and overrides the Web request header for every call to a method in the Project class. If the EnforceWindowsAuth property is true, the GetWebRequest method adds a header that disables Forms authentication. If EnforceWindowsAuth is false, Forms authentication can proceed.

To use the following ASMXLogon_MultiAuth sample, create a console application, follow the steps in Creating the Application and Adding a Web Service Reference, and then add the wsdl.LoginWindows.cs proxy file and the wsdl.Project.cs proxy file. The Main method creates the project instance of the ProjectDerived class. The sample must use the derived LoginWindowsDerived class to get a CookieContainer object for the project.CookieContainer property, which distinguishes Forms authentication from Windows authentication. The project object can then be used to make calls to any method in the SvcProject.Project class.

Note

The LoginWindows service is required only for ASMX applications in a multi-authentication environment. In the ASMXLogon_MultiAuth sample, the GetLogonCookie method gets a cookie for the loginWindows object. The project.CookieContainer property is set to the loginWindows.CookieContainer value.

using System;
using System.Net;
using PSLibrary = Microsoft.Office.Project.Server.Library;

namespace ASMXLogon_MultiAuth
{
    class Program
    {
        private const string PROJECT_SERVER_URL = 
            "https://ServerName/ProjectServerName/_vti_bin/psi/";

        static void Main(string[] args)
        {
            bool isWindowsUser = true;

            // Create an instance of the project object.
            ProjectDerived project = new ProjectDerived();
            project.Url = PROJECT_SERVER_URL + "Project.asmx";
            project.Credentials = CredentialCache.DefaultCredentials;

            try
            {
                // The program works on a Windows-auth-only computer if you comment-out the
                // following line. The line is required on a multi-authentication computer.
                project.CookieContainer = GetLogonCookie();

                project.EnforceWindowsAuth = isWindowsUser;

                // Get a list of all published projects. 
                // Use ReadProjectStatus instead of ReadProjectList,
                // because the permission requirements are lower.
                SvcProject.ProjectDataSet projectDs =
                    project.ReadProjectStatus(Guid.Empty,
                        SvcProject.DataStoreEnum.PublishedStore,
                        string.Empty,
                        (int)PSLibrary.Project.ProjectType.Project);

                Console.WriteLine(string.Format(
                    "There are {0} published projects.", 
                    projectDs.Project.Rows.Count));
            }
            catch (UnauthorizedAccessException ex)
            {
                Console.WriteLine(ex.Message);
            }
            catch (WebException ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Console.Write("Press any key to continue...");
                Console.ReadKey(false);
            }
        }

        private static CookieContainer GetLogonCookie()
        {
            // Create an instance of the loginWindows object.
            LoginWindowsDerived loginWindows = new LoginWindowsDerived();
            loginWindows.EnforceWindowsAuth = true;
            loginWindows.Url = PROJECT_SERVER_URL + "LoginWindows.asmx";
            loginWindows.Credentials = CredentialCache.DefaultCredentials;

            loginWindows.CookieContainer = new CookieContainer();

            if (!loginWindows.Login())
            {
                // Login failed; throw an exception.
                throw new UnauthorizedAccessException("Login failed.");
            }
            return loginWindows.CookieContainer;
        }
    }

    // Derive from LoginWindows class; include additional property and 
    // override the Web request header.
    class LoginWindowsDerived : SvcLoginWindows.LoginWindows
    {
        public bool EnforceWindowsAuth { get; set; }

        protected override WebRequest GetWebRequest(Uri uri)
        {
            WebRequest request = base.GetWebRequest(uri);

            if (this.EnforceWindowsAuth)
            {
                request.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
            }
            return request;
        }
    }

    // Derive from Project class; include additional property and 
    // override the Web request header.
    class ProjectDerived : SvcProject.Project
    {
        public bool EnforceWindowsAuth { get; set; }

        protected override WebRequest GetWebRequest(Uri uri)
        {
            WebRequest request = base.GetWebRequest(uri);

            if (this.EnforceWindowsAuth)
            {
                request.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
            }
            return request;
        }
    }
}

Using the derived LoginWindows class and making PSI calls with a Web request header that disables Forms authentication, is required for applications that run in a multi-authentication environment. If Project Server uses only claims authentication, it is not necessary to derive a class that adds a Web request header. However, the previous example runs in both environments.

The fix for a WCF-based application is different. For more information, see the Using Claims Multi-Authentication section in Prerequisites for WCF-Based Code Samples.

For a complete code sample that uses multi-authentication, see the Samples\MultiAuthentication\ASMXLogon_MultiAuth subdirectory in the Project 2010 SDK download.

Changing the Values of Generic Constants

Most samples have one or more variables that you must update for the sample to work properly in your environment. In the following example, if you have SSL installed, use the HTTPS protocol instead of the HTTP protocol. Replace ServerName with the name of the server that you are using. Replace ProjectServerName with the virtual directory name of your Project Server site, such as PWA.

const string PROJECT_SERVER_URI = "https://ServerName/ProjectServerName/";

Any other variables that you must change or other prerequisites are noted at the top of the code example.

Verifying the Results

Getting and interpreting results from a code sample is not always straightforward. For example, if you create a project, you must publish the project before it can appear on the Project Center page in Project Web App.

You can verify code sample results in the following ways:

  • Use the Microsoft Project Professional 2010 client to open the project from the Project Server computer, and view the items that you want.

  • View the Queue log in Project Web App. In the Quick Launch, click Personal Settings, and then click My Queued Jobs (https://ServerName/ProjectServerName/MyJobs.aspx). In the View drop-down list, you can sort by the job status. The default status is In Progress and Failed Jobs in the Past Week.

  • View published projects on the Project Center page of Project Web App (https://ServerName/ProjectServerName/projects.aspx).

  • Use the Server Settings page in Project Web App to view all queues and enterprise objects (https://ServerName/ProjectServerName/_layouts/pwa/admin/admin.aspx). You must have administrative permissions to access the Server Settings page.

  • Use Microsoft SQL Server Management Studio to run a query on a table of a Project Server database. For example, use the following query to select the top 200 rows of the MSP_WORKFLOW_STAGE_PDPS table to show information about the project detail pages (PDPs) in workflow stages.

    SELECT TOP 200 [STAGE_UID]
          ,[PDP_UID]
          ,[PDP_NAME]
          ,[PDP_POSITION]
          ,[PDP_ID]
          ,[PDP_STAGE_DESCRIPTION]
          ,[PDP_REQUIRES_ATTENTION]
      FROM [ProjectServer_Published].[dbo].[MSP_WORKFLOW_STAGE_PDPS]
    

Cleaning Up

After you test some code samples, there are enterprise objects and settings that should be deleted or reset. You can use the Server Settings page in Project Web App to manage enterprise data (https://ServerName/ProjectServerName/_layouts/pwa/admin/admin.aspx). Links on the Server Settings page enable you to delete old items, force check-in projects, manage the job queue for all users, and perform other administrative tasks.

Following are some of the links on the Server Settings page that you can use for typical cleanup activities after running code samples:

  • Force Check-in Enterprise Objects

  • Server Side Event Handlers

  • Manage Queue Jobs

  • Enterprise Custom Fields and Lookup Tables

  • Delete Enterprise Objects

  • Enterprise Project Types

  • Workflow Phases

  • Workflow Stages

  • Project Detail Pages

See Also

Tasks

How to: Use Impersonation with WCF

Concepts

Overview of WCF and the PSI

Prerequisites for WCF-Based Code Samples

PSI Reference Overview

Other Resources

SharePoint Developer Center