none
PSI CALLS DO NOT WORK IN PROJECT SERVER 2013

    Question

  • Hello folks,

    I now need to make some PSI calls to get some Project Server data, and as I was expecting, PSI CALLS DO NOT WORK IN PS2013 !

    I have created a very simple SharePoint 2013 project (under Visual Studio 2012) aiming at testing PSI calls within an application page. In the page load event of the page, I have added the following code :

    protected void Page_Load(object sender, EventArgs e)
    {
    	    try
                {
                    ProjectContext pj = new ProjectContext("http://ps2013-ts-qve/sandbox/");
                    pj.Load(pj.EnterpriseResources);
                    pj.ExecuteQuery();
                    lblMessage.Text = "PSI Call succeeded!";
                }
                catch (Exception ex)
                {
                    lblError.Text = ex.ToString();
                } }

    The user executing this code is declared as an administrator in PWA, so there shouldn't be any errors, but here is the error I get:

    Access denied. You do not have permission to perform this action or access this resource. at Microsoft.SharePoint.Client.ServerStub.CheckRequiredResourceRight(ProxyContext proxyContext, String memberName, ResourceRight right) at Microsoft.SharePoint.Client.ServerStub.CheckBlockedMethod(String methodName, ProxyContext proxyContext) at Microsoft.ProjectServer.PSContextServerStub.InvokeConstructor(XmlNodeList xmlargs, ProxyContext proxyContext) at Microsoft.SharePoint.Client.ServerStub.InvokeConstructorWithMonitoredScope(XmlNodeList args, ProxyContext proxyContext) at Microsoft.SharePoint.Client.ClientMethodsProcessor.InvokeConstructor(String typeId, XmlNodeList xmlargs) at Microsoft.SharePoint.Client.ClientMethodsProcessor.GetObjectFromObjectPath(XmlElement xe) at Microsoft.SharePoint.Client.ClientMethodsProcessor.GetObjectFromObjectPathId(String objectPathId) at Microsoft.SharePoint.Client.ClientMethodsProcessor.ProcessInstantiateObjectPath(XmlElement xe) at Microsoft.SharePoint.Client.ClientMethodsProcessor.ProcessOne(XmlElement xe) at Microsoft.SharePoint.Client.ClientMethodsProcessor.ProcessStatements(XmlNode xe) at Microsoft.SharePoint.Client.ClientMethodsProcessor.Process()

    ...

    Can someone at MICROSOFT provide the solution to make this code work ???

    Tuesday, February 19, 2013 2:31 PM

All replies

  • If someone at Microsoft cared about this, they would have replied a while ago! This clearly shows that :

    - Firstly, no one has the solution to my problem.

    - Secondly, no one cares about this so-called technology.

    Wednesday, February 20, 2013 1:32 PM
  • The code itself works fine. I copy / pasted and put into a console application and runs no problem.

    I can duplicate your problem putting the same code into a sharepoint application (which is what you've done)

    Therein lies the problem. Do your testing within a console app, not sharepoint app. In a way you are right, you typically wouldn't use the ProjectContext from within Project Server but use the PSI web services instead.

    Hope that helps.


    Wednesday, February 20, 2013 6:37 PM
  • Hello Dave,

    So how am I supposed to get data from project in my webpart or page, any idea ?

    thanks,

    Thursday, February 21, 2013 8:52 AM
  • Hi David. Hopefully we don't diverge too much from original question, but you'd use the PSI web services. Here's a good place to start reading. I'm editting my previous comment. The PSI is fine, it's ProjectContext that is the problem in the above discussion.

    http://msdn.microsoft.com/en-us/library/office/ee767707.aspx

    Thursday, February 21, 2013 6:33 PM
  • Hello,

    I have made a post about this and was following Quentin's too. PSI or CSOM both wont work : 401

    :(

    Thursday, February 21, 2013 6:43 PM
  • As for the original question as to WHY using ProjectContext in 2013 isn't working in Quentin's example, it has to do with client side versus server side. From Microsoft : "The ProjectContext class maintains the client-side context for development with a Project Web App instance."

    So if you think of using javascript, which is client side, you would be using the ProjectContext class. If you are writing say an event handler on a list, you would not use ProjectContext because the event handler is server side.

    Thursday, February 21, 2013 6:47 PM
  • Heres a page that shows how to get Resources in PS2013 from the server side.

    http://msdn.microsoft.com/en-us/library/office/gg221042.aspx

    Quentin's original code at the top shows how to get Resources from the client side.

    that's about it. Don't think I can provide any more answer than that. Try reading the following, which has sections "Using the PSI" and "Using the CSOM":

    http://msdn.microsoft.com/en-us/library/office/ms504195.aspx#pj15_Programmability_PSI

    and for clarification, the original question using ProjectContext is an example of CSOM, which is itself an interface to the PSI. The PSI is accessed through web services.

    Tuesday, February 26, 2013 5:42 PM
  • Hello Dave,

    From the server side I have always used the PSI (And your first link actually uses PSI). I know all the things you are linking, but maybe I missed something, since PS 2013 I always get Unauthorized 401.

    David

    Monday, March 4, 2013 8:54 AM
  • I'd sugget putting your code (if you are using projectcontext) into a console application, basically using the original code Quinten posted. Run that. If it works, good. If it doesn't work, I'd look at user permissions.

    Assuming it does work, no reason why it wouldn't, then you'll know that you can user projectcontext FROM CLIENT SIDE code. I suspect you, like Quinten, are trying to use projectcontext on SERVER SIDE code. this worked fine in 2010 because everything ran server side. In 2013 it's seperated between server side and client side, and projectcontext only works on the client side.

    You could always psot complete code, and I can take a look

    Thursday, March 21, 2013 6:05 AM
  • Hello Dave,

    Yes it works in a console app. Both PSI and CSOM won't work in Sharepoint, so what code should i use ?

    My code

           protected void Page_Load(object sender, EventArgs e)
            {
                const string PROJECT_SERVER_SERVICE = "/_vti_bin/PSI/ProjectServer.svc";
                const int MAX_SIZE = 500000000;
                BasicHttpBinding httpBinding;
                EndpointAddress address;
                Uri pwaUri = new Uri("http://myserver/myinstance");
                string pwaUrl = pwaUri.Scheme + Uri.SchemeDelimiter + pwaUri.Host + ":"
                   + pwaUri.Port + pwaUri.AbsolutePath;
                httpBinding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);
    
                httpBinding.Name = "basicHttpConf";
                httpBinding.SendTimeout = TimeSpan.MaxValue;
                httpBinding.MaxReceivedMessageSize = MAX_SIZE;
                httpBinding.ReaderQuotas.MaxNameTableCharCount = MAX_SIZE;
                httpBinding.MessageEncoding = WSMessageEncoding.Text;
                httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
    
                // The endpoint address is the ProjectServer.svc router for all public PSI calls.
                address = new EndpointAddress(pwaUrl + PROJECT_SERVER_SERVICE);
                ResourceClient client = new ResourceClient(httpBinding, address);
                client.ChannelFactory.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
                client.GetCurrentUserUid();
            }

    Error:

    The HTTP request is unauthorized with client authentication scheme 'Ntlm'. The authentication header received from the server was 'NTLM,Negotiate'.


    Thursday, March 21, 2013 11:30 AM
  • David, notice that your error is different than the original error, which was access denied.

    You have a different problem entirely, unauthorized for NTLM. I suggest searching for that, and starting a new thread if you are still having problems.

    Friday, March 22, 2013 4:24 AM
  • Hello Dave,

    Thanks for trying to help but please actually try the code. This has been the generic unauthorized error for ages. If I set the credentials to the ResourceClient everything works, I just want that it uses currently connected user rights.

    As MS doesn't give us any sample and let us lose time, I just hope a dev actually succeeded doing that.

    There the innerexception:

    {"The remote server returned an error: (401) Unauthorized."}

    Friday, March 22, 2013 9:04 AM
  • Hi

    Has anyone found solution for thi?

    Thursday, April 4, 2013 8:16 PM
  • My guess is it has something to do with the claims authentication (which is enabled by default now).


    • Edited by Tomaz_K Saturday, April 6, 2013 9:06 AM
    Saturday, April 6, 2013 9:06 AM
  • I think I got it.

    Down bellow is an example how to call simple PSI call on behalf of user who is calling sharepoint. The original problem is in ClaimAuthentication. Solution consists of two parts:

    1. From Claims Identity get Windows Identity for calling user
    2. Use Windows Identity and perform impersonation when performin PSI call

    I haven't tested this with CSOM yet, but I think is the same.

    public string GetCurrentUserId()
    {
        string userName = string.Empty;
    
        // first convert claims login name to windows (this is of form DOMAIN\username)
        // then split DOMAIN\username by '\'
        Microsoft.SharePoint.Administration.Claims.SPClaimProviderManager mgr = Microsoft.SharePoint.Administration.Claims.SPClaimProviderManager.Local;
        string[] result = null;
        if (mgr != null)
        {
            userName = mgr.DecodeClaim(SPContext.Current.Web.CurrentUser.LoginName).Value;
            result = userName.Split('\\');
        }
    
        // perform impersonation of your AppPool account (must has access to Claims2Windows Service)
        // give him UPN username (this is of form username@DOMAIN)
        WindowsIdentity windowsIdentity = null;
        using (WindowsIdentity.Impersonate(IntPtr.Zero))
        {
            windowsIdentity = Microsoft.IdentityModel.WindowsTokenService.S4UClient.UpnLogon(result[1] + "@" + result[0]);
        }
    
        // perform impersonation of your user who is calling SharePoint
        // call PSI method on behalf of the calling user
        using (windowsIdentity.Impersonate())
        using (var resourceClient = new ResourceClient(new System.ServiceModel.BasicHttpBinding("PSSVCBinding"), new System.ServiceModel.EndpointAddress(String.Format(CultureInfo.InvariantCulture, "{0}/_vti_bin/PSI/ProjectServer.svc", SPContext.Current.Site.RootWeb.Url.TrimEnd('/')))))
        {
            return resourceClient.GetCurrentUserUid().ToString();
        }
    } 
    • Proposed as answer by Renke Holert Sunday, April 7, 2013 5:05 PM
    Saturday, April 6, 2013 11:20 AM
  • Hi All! You can find more information about this issue at http://www.projectserver2010blog.com/2013/04/project-server-2013-psi-from-web.html
    Saturday, May 4, 2013 12:28 PM