Here you can find some description of how to use FluentPS to access the ProjectServer instance.

PS Entity Mapping with custom attributes

You can map 3 basic types of ProjectServer entities - Project, Resource and Task - onto your .Net classes. This can be done with help of custom attributes for classes' properties.
public class Project
    [PSEntityUidField(ColumnName = ProjectCustomFieldsColumnNames.PROJ_UID)]
    public Guid Uid { get; set; }

    [PSNativeField(ColumnName = ProjectCustomFieldsColumnNames.PROJ_NAME)]
    public string Name { get; set; }

    [PSCustomField("{_Custom_Field_UID_}", FieldName = "Field Name")]
    public string TextCustomField { get; set; }

    [PSCustomField("{Custom_Field_UID}", FieldName = "Field Name")]
    public decimal NumberCustomField { get; set; }

    [PSCustomField("{Custom_Field_UID}", FieldName = "Field Name")]
    public DateTime DateCustomField { get; set; }

    [PSLookupField("{Custom_Field_UID}", "{Lookup_Table_UID}",
        FieldName = "Field Name", LookupTableName = "Lookup Table Name")]
    public string TextLookupField { get; set; }

    [PSLookupField("{Custom_Field_UID}", "{Lookup_Table_UID}",
        FieldName = "Field Name", LookupTableName = "Lookup Table Name")]
    public string HierarchialLookupField { get; set; }

    [PSLookupField("{Custom_Field_UID}", "{Lookup_Table_UID}",
        FieldName = "Field Name", LookupTableName = "Lookup Table Name")]
    public IList<string> MultiselectLookupField { get; set; }

It is shown in this code, there are 4 custom attributes in FluentPS which can be used for mapping project entities:
  • PSEntityUidField - used to map entity Uid field
  • PSNativeField - used to map native entity fields i.e. Name and Description
  • PSCustomField - used to map entity custom fields
  • PSLookupField - used to map custom fields related to lookup tables
The type of property is used to determine the type of the custom field. Thereforethe following type correlation table should be used:
ProjectServer type .Net type
Cost -
Date DateTime
Duration int
Flag bool
Number int, decimal
Text string
Lookup Multiselect IEnumerable<string> + descentants

Entity Access Services

To perform Read/Update operations you should use corresponding services instantiated for the type of entity you are working with:
Here are the generic service types which should be used to access ProjectServer entities.
  • PSProjectService<> - performs operations with ProjectServer projects
  • PSResourceService<> - performs operations with ProjectServer resources
  • PSTaskService<> - performs operations with ProjectServer tasks
Here is the example:
var projectsService = new PSProjectService<Project>(...);
var resourcesService = new PSResourceService<Resource>(...);
var tasksService = new PSTaskService<Task>(...);

As far as these services depend upon other services passed to the services' constructors, you can use IoC or any other conception to get the service instances in a handy way.

Read/Update operations

To change Custom Field value of the entity you've read from the ProjectServer, you can simply set a new value into the mapped property:
var project = projectsService.Get(new Guid("{Project_UID}"));
project.TextCustomField = string.Format("{0} updated", project.TextCustomField);
project.NumberCustomField = project.NumberCustomField + 1;
project.DateCustomField = DateTime.Now;
project.TextLookupField = "Another Lookup Table Value"; 
project.HierarchialLookupField = "Parent Lookup Value 1.Child Lookup Value 1"; 
project.MultiselectLookupField.Add("Not Selected Lookup Value"); 
project.MultiselectLookupField.Remove("Selected Lookup Value"); 

Here is the code which updates mapped entity and all it's custom fields:
var queueService = new PSQueueSystemService(...);
var jobId = projectsService.CheckIn(project.Uid, Guid.NewGuid());
// wait for queue

Guid sessionId = Guid.NewGuid();
projectsService.CheckOut(project.Uid, sessionId);

jobId = projectsService.Update(project, sessionId);

jobId = projectsService.Publish(project.Uid, false);

jobId = projectsService.CheckIn(project.Uid, Guid.NewGuid());

Last edited Jan 22, 2010 at 12:15 PM by AndrewGrushewsky, version 31


devi_ous Oct 28, 2015 at 4:16 PM 
Viola, it works!
Quick start example:

var logService = new ConsoleLogService();
var ltc = Helpers.CreateProxy<LookupTableClient, FluentPS15.WebSvcLookupTable.LookupTable>(url, "/_vti_bin/PSI/LookupTable.asmx");
var cfc = Helpers.CreateProxy<CustomFieldsClient, CustomFields>(url, "/_vti_bin/PSI/CustomFields.asmx");
var prc = Helpers.CreateProxy<FluentPS15.WebSvcProject.ProjectClient, FluentPS15.WebSvcProject.Project>(url, "/_vti_bin/PSI/Project.asmx");
var lookupTableService = new PSLookupTableService(logService, ltc, null);
var cfService = new PSCustomFieldService(logService, cfc, null, null, lookupTableService);

var projectsService = new PSProjectService<Project>(logService, lookupTableService, cfService, null, prc);

devi_ous Oct 28, 2015 at 3:01 PM 
Please show example how to create PSProjectService with all parameters.
I try huge amount of version but not found one working set of cascade nested monster classes.
Try for a hour and never get program compiled.
Library is unusable