Updating Project Server custom fields via JSOM

After a few busy weeks working on my first 100% JavaScript 2013 App (watch this space for more!!) I’ve come to realise that the MSDN documentation on JSOM and CSOM still is pretty sparse!

A couple of simple examples exist in the usual place (e.g. JSOM CreateProjects) but when you get to the details you’ll find a lot missing. For example updating Custom Fields; if you look at the MSDN page covering PS.DraftProject, the method you need (draftProject.setCustomFieldValue()) is not even listed! (UPDATE 7/08: It is covered here but with no detail; PS.Project.setCustomFieldValue)

 

JavaScript PS.DraftProject.setCustomFieldValue Method

Here’s the missing method definition that you’ll see when using PS.debug.js:

PS.DraftProject.setCustomFieldValue(FieldName, Value);

Hey wow, that simple hey? No, unfortunately the definition is a bit misleading; easy to assume that FieldName references the custom field name used else where like in the OData fields, but in fact this refers to the InternalName from the PS.CustomField object.

An example InternalName is: Custom_a1737ae3b4fce211940b00155d000a03

So first thing you need to do is get that name, it is just the field GUID prefixed with “Custom_”, but I like to do things more dynamically so I’ll use projContext.get_customFields(); to cache that information.

 

Example JavaScript update of Custom Field Value

Firstly lets get those InternalName values into an array for later use.

Cache the field details with a GetCustomFields Function

var projContext;
var customFields;
var customFieldData = [];


SP.SOD.executeOrDelayUntilScriptLoaded(GetCustomFields, "PS.js");


function GetCustomFields() {
    // Initialize the current client context and get the projects collection
    projContext = PS.ProjectContext.get_current();


    customFields = projContext.get_customFields();
    projContext.load(customFields);

    // Run the request on the server.
    projContext.executeQueryAsync(getCFComplete, getCFFailed);
}

function getCFComplete(response) {
    var cfEnumerator = customFields.getEnumerator();


    // Save the details of each CF for later
    while (cfEnumerator.moveNext()) {
        var cf = cfEnumerator.get_current();


        customFieldData.push({
            Id: cf.get_id(),
            Name: cf.get_name(),
            InternalName: cf.get_internalName()
        });
    }

    // Now update the project
    updateProject();
}

Note the last line there; updateProject() as this is all asynchronous you need to call the update only once you have the customFieldData array ready.

 

Update the Project Custom Field Function

function updateProject() {
    var projectId = "9C585CC0-3FC0-4133-9F2A-1FB96587CF0D";
    var project = projects.getById(projectId);
    var draftProject = project.checkOut();
    var fieldName = "My Custom Field";


    // Update custom field
    var cfData = $.grep(customFieldData, function (val) {
        return val.Name === fieldName;
    });

    if (cfData.length > 0) {
        draftProject.setCustomFieldValue(cfData[0].InternalName, "Some new value");
    }

    //Publish the change
    var publishJob = draftProject.publish(true);


    //Monitor the job
    projContext.waitForQueueAsync(publishJob, 30, function (response) {
        if (response !== 4) {
            // handle errors
        }
    }
}

This simple example assumes the FieldType is text, but you get the idea, also to work with Lookup Tables you’ll need to look at the cf.get_lookupEntries() values in the getCFComplete() function but hopefully the above will get you started.

Share and Enjoy !

Shares

PSI in 2013: Unhandled Communication Fault occurred

I’ve had the fun task of shoe-horning some 2010 PSI projects into Project Server 2013 recently, and the good news is that as promised the PSI is still there just as we remember it!

One particular exception I kept seeing in my code immediately when using SharePoint Permissions Mode (ie a Default install) was the following:

Exception: Unhandled Communication Fault occurred

 

Which came with the unusually helpful accompanying ULS log errors;

06/11/2013 10:05:54.39        w3wp.exe 0x161C)  0x29B0        Project Server  General  ab3be   Monitorable    Unhandled exception in the process of routing the request to the app server: Target=https://host/PWA/_vti_bin/PSI/ProjectServer.svc, exception=[InvalidOperationException] Operation is not valid due to the current state of the object., StackTrace= at Microsoft.Office.Project.Server.WcfTrustedFacadeHelperMethods.
TryGetImpersonationContextInfo(String originalTargetUrl, OperationContext context, ImpersonationHeader& impersonationHeader) …

06/11/2013 10:05:54.39       w3wp.exe (0x161C)  0x29B0        Project Server  Security  aibp8     High        Impersonation is not supported in SharePoint permission mode

 

The second log is the giveaway, I won’t be forgetting that limitation again!

Share and Enjoy !

Shares

MS Reporting (Project Publish) jobs Failed after AprilCU

This is one that has been causing me some grief the past couple of weeks, after apply Project Server 2013 April CU (KB2737990) a couple of customers started reporting the following errors intermittently in the queue:

GeneralQueueJobFailed (26000) – ReportingProjectPublish.ReportProjectPublishMessageEx. Details: id=’26000′ name=’GeneralQueueJobFailed’ uid=’b62dc86f-30cf-e211-9409-00155d11030a’ JobUID=’2cc0c869-30cf-e211-9409-00155d11030a’ ComputerName=…

General Reporting message processor failed: ReportingProjectChangeMessageFailed (24006) – Object reference not set to an instance of an object.. Details: id=’24006′ name=’ReportingProjectChangeMessageFailed’ uid=’beef9169-30cf-e211-9409-00155d11030a’ QueueMessageBody=’Project UID=’e296653a-30cf-e211-9409-00155d11030a’. PublishType=’ProjectPublish” Error=’Object reference not set to an instance of an object.’. …

 

The ULS log indicates the source of this one:

PWA:, ServiceApp:Project Service Application, User:i:0?.t|liveid|…=, PSI: [RDS] ULS Event: ReportingProjectChangeMessageFailed was associated with exception: System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Office.Project.DataEdit.Reporting.ReportingData.
GetTaskBaselineCoreTimephasedDataSetInternal(BaselineEntity[] baselineEntityArray, Int32 nIntervalLengthMinutes, Boolean enforceMaxRowLimit, Int32& index)
at Microsoft.Office.Project.Server.DataAccessLayer.
TaskBaselinesTimephasedDataSync.GetTimephasedDataForEntities(IEnumerable`1 entities, Int32 interval, Int32& index)

 

So something is wrong in the baseline, unfortunately turns out to be nothing small!

Looks like ANY task with 0 duration causes this failure, yes that’s right any milestone included in the baseline!

Microsoft have confirmed this one just today so I certainly won’t be installing AprilCU ever again, however currently no workaround exists, so if like me you are stuck with this then for now take it up with Microsoft as they will hopefully have a fix ASAP, otherwise I’ll update this post when I learn more.

 

HTH,

Update 2/10/2013:

Thanks Carl Dalton for testing and confirming that an old workaround to a similar issue for 2007 actually fixes this one: http://carl-projectserver.blogspot.com.au/2013/09/issues-update-on-projectserver2013.html

Update 16/10/2013:

The Microsoft Hotfix is out in the October 2013 CU, see the actual KB and go download the patch: http://support.microsoft.com/kb/2825659/en-us

Share and Enjoy !

Shares

PWA Provisioning in 2013 or ‘Look no site collection!’

A few people have written about PowerShell provisioning of PWA in 2013, see here and here, both reference this TechNet source. However if you’re anything like me you might find these confusing! Coming from 2010 it seems that everything has changed, so after struggling a bit using the above three references trying to update my old automated PWA deployment scripts I figured that it can’t hurt to have one more guide online covering the process.

 

Look No Site Collection

Firstly though, one of the great things about 2013 is that PWA is now uncoupled from its Site Collection, basically /PWA no longer needs to be a Site Collection but can be any regular site.

Esoteric as that may sound it means that we no longer have this odd divide where Project data such as Project Sites live in various “SharePoint Intranet” site collections and PWA has to be in it’s own isolated space with different users, permissions, features, etc. Clearly this is geared towards supporting SharePoint permissions mode and generally making Project more SharePoint friendly, but combined with those nifty new license management features things become very much easier for many of us dealing with real world deployment scenarios.

This also has the added bonus of making it easier to provision PWA at the root site collection (in a more standard way – ick Site Collection host headers!).

 

Get to the setup

The challenge I had with the scripted setup links above was that they seemed to be missing something, for instance the TechNet article misses the whole site collection creation part and so then confuses things by splitting off into a separate article on creating PWA in an existing site collection? Is it just me or was that really confusing?

Anyway here’s my PowerShell script for provisioning a new PWA instance in a new Site Collection where the root site collection contains a Team Site and PWA is in the familiar location /PWA.

$SiteUrl = "https://"+$HostHeader
$PWASiteUrl = "https://"+$HostHeader+$PWAPath
$SiteCollectionOwner="i:0#.w|domain$($AdminUser)"
$SecondaryOwnerAlias=""
$PWADatabase="ProjectWebAppDB"
$DatabaseServer = "sqlservername"
$PWAAbbreviation = "PWAInstance1"

$svcApp = Get-SPServiceApplication | ? {$_.TypeName -eq 'Project Application Services'}
$webapp = Get-SPWebApplication -Identity $SiteUrl


Write-Host "Creating Project Server database:" $PWADatabase
New-SPProjectDatabase -Name $PWADatabase -ServiceApplication $svcApp `
    -DatabaseServer $DatabaseServer -Tag $PWAAbbreviation `
    -ErrorVariable err
if ( $err ) {
    write-host "An Error Occured: " $err -ForegroundColor Red
    break
}


Write-Host "Creating Team Site root for PWA" $SiteUrl " Owner:" $SiteCollectionOwner
$site = New-SpSite -url $SiteUrl `
    -owneralias $SiteCollectionOwner `
    -SecondaryOwnerAlias $SecondaryOwnerAlias `
    -ErrorVariable err
if ( $err ) {
    write-host "An Error Occured: " $err -ForegroundColor Red
    break
}

Write-Host "Creating PWA Web: " $PWASiteUrl " Owner:" $SiteCollectionOwner
$web = New-SPweb -URL $PWASiteUrl -Template pwa#0

$web=Get-SPWeb $SiteUrl
$web.Properties["PWA_TAG"] = $PWAAbbreviation
$web.Properties.Update()

Write-host "Enabling PWASite features..."
Enable-SPFeature pwasite -URL $SiteUrl

I lifted that from my mass deployment script (woo 2,600 lines and counting) so after my little rant above please excuse me if I forgot to declare one of the variables or something.

 

Hope this helps someone!

 

This article is republished with permission here: EPMonDemand Blog

Share and Enjoy !

Shares

License Management in 2013

One of the few questions that I have regularly been asked by just about every customer I have ever worked with is about licensing. Unfortunately I don’t have an MS Degree in the topic, as these days it seems you need to have one! It’s far too easy to get conflicting advise as to how and what features can be used with what license. E.g. Can a non-PWA CAL see Project Server reports?

Fortunately in the 2013 SharePoint and Project Server release Microsoft have given us what I consider to be the best kind of answer; a technical one! You can’t get more accurate that a error message stating that you do not have a license to view this content!

Read More: Introduction to User License Enforcement in SharePoint Server 2013

Finally I can tell customers that those PWA CALs can be used for *this*, and the rest of your users just need *that*!

 

Enabling Project User License Mapping

The link above talks about what you need to know to setup the new License Mapping feature, but here’s a quick summary;

1. Enable the feature via PowerShell;

Enable-SPUserLicensing

2. Create a mapping to your Active Directory “Team Members” (or other) group;

$map = New-SPUserLicenseMapping -SecurityGroup "DOMAINPS Team Members" -License Project

3. Finally add the mapping to the farm

Add-SPUserLicenseMapping -Mapping $map

 

Note: By completing step #1 above you will DENY all users access to Project and other SharePoint features (including Enterprise Features and Office Web Apps), that is until you run steps #2 and #3 for all the license types which you need to map.

 

Effects of Project License Mapping

Now the interesting part, given two users: Me and my favourite resource Test User what when I am the only licensed user (a member of Team Members AD group), what is restrictions are enforced on Test User?

First and foremost, when Test User tries to open PWA this is what he gets:

image

Good stuff, but what about if I assign some work to Test and share my site with him?

image

Now this is promising, what about Risks / Issues, etc?

image

 

Looks like that permission only restricts PWA access, this is actually exactly what I wanted (to be clear; exactly what many customers have asked me for in the past).

Lastly what about Reports?

image

Looks like Test can get to BI centre (via URL directly not PWA) once it’s shared!

 

The Catch?

I honestly don’t know.

I suspect that there may be one as all previous advice I have had from Microsoft is that, quote; ‘Any user who accesses any Project data must be licensed.

However as I said before, technical answers (true / false style) make me rather more comfortable about the truth of a particular question as opposed to conflicting advice.

 

Disclaimer

Do not take this blog as licensing advice, I do not work for Microsoft (that was a long time ago) and the views expressed here are entirely my own.

Speak to your Microsoft Reseller or Account Manager if you have any specific licensing questions.

Share and Enjoy !

Shares