I have the MS Project Online account at sharepoint.com and I need to authenticate from client C# code to PSI services to get list of projects.
Server has Forms based authentication. I am trying to login via next code:
SvcLoginForms.LoginForms loginform = new SvcLoginForms.LoginForms();
loginform.Credentials = new NetworkCredential("admin#myserver.onmicrosoft.com", "password");
loginform.Url = "https://myserver.sharepoint.com/sites/pwa/_vti_bin/PSI/Project.asmx";
loginform.Login("admin#myserver.onmicrosoft.com", "password");
When I am executing loginform.Login I am getting SoapException with message: "Value cannot be null. Parameter name: account". Inner exception xml is:
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Value cannot be null.
Parameter name: account
What I am doing wrong?
You can use:
new SharePointOnlineCredentials(username, secpassword);
instead of
new NetworkCredential("admin#myserver.onmicrosoft.com", "password");
First: Install required Client SDK
SharePoint Client SDK :
http://www.microsoft.com/en-au/download/details.aspx?id=35585
Project 2013 SDK:
http://www.microsoft.com/en-au/download/details.aspx?id=30435
Second: add the reference to your project
Microsoft.SharePoint.Client.dll
Microsoft.SharePoint.Client.Runtime.dll
Microsoft.ProjectServer.Client.dll
You can find the dlls in %programfiles%\Common Files\microsoft shared\Web Server Extensions\15\ISAPI
and %programfiles(x86)%\Microsoft SDKs\Project 2013\REDIST
Here is sample code:
using System;
using System.Security;
using Microsoft.ProjectServer.Client;
using Microsoft.SharePoint.Client;
public class Program
{
private const string pwaPath = "https://[yoursitehere].sharepoint.com/sites/pwa";
private const string username ="[username]";
private const string password = "[password]";
static void Main(string[] args)
{
SecureString secpassword = new SecureString();
foreach (char c in password.ToCharArray()) secpassword.AppendChar(c);
ProjectContext pc = new ProjectContext(pwaPath);
pc.Credentials = new SharePointOnlineCredentials(username, secpassword);
//now you can query
pc.Load(pc.Projects);
pc.ExecuteQuery();
foreach(var p in pc.Projects)
{
Console.WriteLine(p.Name);
}
//Or Create a new project
ProjectCreationInformation newProj = new ProjectCreationInformation() {
Id = Guid.NewGuid(),
Name = "[your project name]",
Start = DateTime.Today.Date
};
PublishedProject newPublishedProj = pc.Projects.Add(newProj);
QueueJob qJob = pc.Projects.Update();
JobState jobState = pc.WaitForQueue(qJob,/*timeout for wait*/ 10);
}
}
Authentication to Project Online PSI services is described in this excellent article: http://www.umtsoftware.com/blog/how-to-project-online-psi/
Related
I have signed up for the Office 365 Developer Edition with Microsoft 365 E5 Developer (without Windows and Audio Conferencing). I am writing codes to connect to the Sharepoint of developer domain. Following are my codes:
public static String GetList( ICredentials credentials)
{
var authManager = new OfficeDevPnP.Core.AuthenticationManager();
using (ClientContext clientContext =
authManager.GetWebLoginClientContext("https://xxx.sharepoint.com"))
{
clientContext.Credentials = credentials;
Web web = clientContext.Web;
clientContext.Load(web,
webSite => webSite.Title);
clientContext.ExecuteQuery();
return web.Title;
}
}
public string callSharepoint()
{
const string userName = "Username#domain.onmicrosoft.com";
const string password = "xxxx";
var securePassword = new SecureString();
foreach (var c in password)
{
securePassword.AppendChar(c);
}
var credentials = new SharePointOnlineCredentials(userName, securePassword);
var list = GetList(credentials);
return list.ToString();
}
While running, it first asks to enter Microsoft Office credentials, and then it does verification by sending code to contact number and then after verification is completed it throws an Exception on Line
clientContext.ExecuteQuery(). The Exception is as follow:
Microsoft.SharePoint.Client.IdcrlException: 'The sign-in name or password does not match one in the Microsoft account system.'
The credentials I am using is of Admin Account with role Global Administrator. I also tried to add new user account in that Active Directory and tried that credentials but still got the same exception on the same place.
I even try to remove Pnp Authorization, Enable and disable Multi factor Authorization, but no success. However, I can successfully log in into the Sharepoint site on browser by using exactly same credentials.
What I think is, there is most likely a problem in the setup which I did while setting office account developer subscription. And maybe nothing is wrong with the code because I used the same codes to log in to my organization's Sharepoint and it works perfectly fine. Maybe I need something else to be configured in my developer's Office Account.
Please let me know if anyone already has some knowledge about this problem.
You have init the credential so you could use it directly, if issue exists, should be related to your user account or license.
public static String GetList(ICredentials credentials)
{
//var authManager = new OfficeDevPnP.Core.AuthenticationManager();
//using (ClientContext clientContext =
//authManager.GetWebLoginClientContext("https://xxx.sharepoint.com/sites/lee"))
//{
//}
using (ClientContext clientContext = new ClientContext("https://xxx.sharepoint.com/sites/lee"))
{
clientContext.Credentials = credentials;
Web web = clientContext.Web;
clientContext.Load(web,
webSite => webSite.Title);
clientContext.ExecuteQuery();
return web.Title;
}
}
public string callSharepoint()
{
const string userName = "user#xxx.onmicrosoft.com";
const string password = "password";
var securePassword = new SecureString();
foreach (var c in password)
{
securePassword.AppendChar(c);
}
var credentials = new SharePointOnlineCredentials(userName, securePassword);
var list = GetList(credentials);
return list.ToString();
}
Ok I found the solution.
That is I don't need this line of code:
clientContext.Credentials = credentials;
Since MFA is enabled, so when I logged in via Pnp Authenticator, it should use that user account. Instead of the one which is passed via SharePointOnlineCredentials.
"Operation has timed out" error while connecting to Office 365 Sharepoint from asp.net web application
I have tried finding answers and implementing solutions like below:
How to connect to SharePoint on Office 365 with CSOM from C#?
Also some blogs suggested making an asynchronous query, which does not throw error but also does not give any results.
Also tried setting timeout property without any help.
Below is my code:
SharePointOnlineCredentials networkCredential = new
SharePointOnlineCredentials(SharePointUser, SharePointPassword);
Context = new ClientContext(SharePointURL);
Context.Credentials = networkCredential;
Web = Context.Web;
Context.Load(Web);
Context.ExecuteQuery();`
Also, strangely I am able to connect and get data using Console application, but I need to get this working in web application.
After a lot of search I realized that we need proxy to connect to Sharepoint Online and implemented following code to achieve
clientContext.ExecutingWebRequest += (s, e) =>
{
e.WebRequestExecutor.WebRequest.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
};
Add clientContext.RequestTimeout = -1 in the code, the code below for your reference.
string siteUrl = "https://tenant.sharepoint.com/sites/lz";
string userName = "lz#tenant.onmicrosoft.com";
string password = "xxx";
var securePassword = new SecureString();
foreach (char c in password.ToCharArray()) securePassword.AppendChar(c);
using (ClientContext clientContext = new ClientContext(siteUrl))
{
clientContext.Credentials = new SharePointOnlineCredentials(userName, securePassword);
clientContext.RequestTimeout = -1;
var web = clientContext.Web;
clientContext.Load(web);
clientContext.ExecuteQuery();
}
I am having problems accessing SharePoint using both CSOM and the REST service from a .NET Core console application.
First I created a console application that targets .NET Framework 4.6.1, installed the Microsoft.SharePointOnline.CSOM nuget package, and added two sample methods to connect to SharePoint using hard-coded user credentials. This works.
public static void CsomCall()
{
var password = "password";
var securePassword = new SecureString();
foreach (var c in password.ToCharArray()) securePassword.AppendChar(c);
using (ClientContext context = new ClientContext("https://siteurl"))
{
context.Credentials = new SharePointOnlineCredentials("user#domain", securePassword);
Web web = context.Web;
context.Load(web);
context.ExecuteQuery();
Console.WriteLine(web.Title);
}
}
private static void RestCall()
{
var password = "password";
var securePassword = new SecureString();
foreach (var c in password.ToCharArray()) securePassword.AppendChar(c);
var credentials = new SharePointOnlineCredentials("user#domain", securePassword);
using (WebClient client = new WebClient())
{
client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
client.Credentials = credentials;
client.Headers.Add(HttpRequestHeader.ContentType, "application/json;odata=verbose");
client.Headers.Add(HttpRequestHeader.Accept, "application/json;odata=verbose");
var content = client.DownloadString("https://siteurl/_api/web/lists");
Console.WriteLine(content);
}
}
Then I created a .NET Core console application and copied across the methods above. I understand that SharePoint CSOM is not yet supported in .NET Core, so I used the workaround suggested here and manually referenced Microsoft.SharePoint.Client.Portable.dll, Microsoft.SharePoint.Client.Runtime.Portable.dll and Microsoft.SharePoint.Client.Runtime.Windows.dll.
I had to make a couple of changes to compile the code:
.ExecuteQueryAsync() instead of .ExecuteQuery()
var credentials = new SharePointOnlineCredentials("user#domain", password); Note, password is a plain string in Microsoft.SharePoint.Client.Runtime.Portable.
When running CsomCall it fails when accessing web.Title:
Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException: 'The property or field 'Title' has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.'
When running RestCall it fails with an error on client.DownloadString:
System.Net.WebException: 'The remote server returned an error: (401) Unauthorized.'
Is it possible to set up SharePointOnlineCredentials to work with .NET Core? Searches on stack overflow indicate this should be possible, but I just can't seem to make it work.
Ultimately we would like to build a Web API service using ASP.NET Core to generate documents for internal users (reading document templates from SharePoint, generating a new document and saving back to SharePoint). Using either CSOM or REST, and running on Windows OS for now.
The REST call is wrong. You have to get a token using the credentials. Also, the WebClient is mostly deprecated, use the HttpClient class instead.
Look at this example:
public const string BaseUri = "https://example.sharepoint.com";
private static HttpClient _client;
public static void Initialize()
{
SharePointOnlineCredentials currentCredentials = GetCredentialsHere();
var handler = new HttpClientHandler
{
Credentials = currentCredentials
};
_client = new HttpClient(handler);
// you are missing this line
handler.CookieContainer.SetCookies(BaseUri, currentCredentials.GetAuthenticationCookie(BaseUri));
_client.BaseAddress = BaseUri;
_client.DefaultRequestHeaders.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_client.MaxResponseContentBufferSize = 2147483647;
}
I tried to get all members/users of TFS with the REST API and the .NET client libraries.
It works, but I get a maximum number of 50 identitys. Does anyone know, how I get all users, not only 50? (I prefer avoiding to use the old API, how it is suggested in this question)
Here is my code:
VssCredentials credentials = new VssCredentials();
VssConnection connection = new VssConnection(new Uri(url), credentials);
IdentityMruHttpClient identityMruHttpClient = connection.GetClient<IdentityMruHttpClient>();
List<IdentityRef> members = identityMruHttpClient.GetIdentityMruAsync(ProjectName).Result;
There is a REST API User Entitlements - List which can retrieve the user list from VSTS (Visual Studio Team Services), but it's only available for VSTS.
There isn't such a REST API to retrieve the user list from on-premise TFS (TFS 2017 in your scenario).
So, for now you can use the client API you mentioned above to retrieve the user list. Tested on my side, I can retrieve all the identities (more than 50 ) with below code:
You can also check the user list from userlist.txt file which under ..\..\ \bin\Debug\
using System;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using System.Linq;
using System.IO;
namespace Getuserlist
{
class Program
{
static void Main(string[] args)
{
TfsConfigurationServer tcs = new TfsConfigurationServer(new Uri("http://server:8080/tfs"));
IIdentityManagementService ims = tcs.GetService<IIdentityManagementService>();
TeamFoundationIdentity tfi = ims.ReadIdentity(IdentitySearchFactor.AccountName, "Project Collection Valid Users", MembershipQuery.Expanded, ReadIdentityOptions.None);
TeamFoundationIdentity[] ids = ims.ReadIdentities(tfi.Members, MembershipQuery.None, ReadIdentityOptions.None);
using (StreamWriter file = new StreamWriter("userlist.txt"))
foreach (TeamFoundationIdentity id in ids)
{
if (id.Descriptor.IdentityType == "System.Security.Principal.WindowsIdentity")
{ Console.WriteLine(id.DisplayName); }
//{ Console.WriteLine(id.UniqueName); }
file.WriteLine("[{0}]", id.DisplayName);
}
var count = ids.Count(x => ids.Contains(x));
Console.WriteLine(count);
Console.ReadLine();
}
}
}
I've having difficulty following this guide
http://dotnetbyexample.blogspot.co.uk/2011/03/sharepoint-client-object-model-sites.html
I've created the helper class as advised:
namespace TestSharepoint
{
public class SharepointHelper
{
private ClientContext clientContext;
private Web rootWeb;
public SharepointHelper(string url, string username, string password)
{
clientContext = new ClientContext(url);
var credentials = new NetworkCredential(username, password, "oshirowanen.com");
clientContext.Credentials = credentials;
rootWeb = clientContext.Web;
clientContext.Load(rootWeb);
}
}
}
However, I do not want to create another site, as I already have a site, so I wanted to test the next part by retrieving the existing sites title:
public Web GetWebByTitle(string siteTitle)
{
var query = clientContext.LoadQuery(
rootWeb.Webs.Where(p => p.Title == siteTitle));
clientContext.ExecuteQuery();
return query.FirstOrDefault();
}
and added this to the form load event:
var sh = new SharepointHelper("https://sharepoint.oshirowanen.com/sites/oshirodev/", "sharepoint_admin_user", "sharepoint_admin_password");
var w = sh.GetWebByTitle("Oshirowanen SharePoint");
Console.WriteLine(w.Title);
What I am getting confused about is, why I am typing in the title of the site which I want to receive the title of??? So I think I am not using this properly?
The error I get is:
An unhandled exception of type 'System.NullReferenceException' occurred in SharePointProgramming.exe
Additional information: Object reference not set to an instance of an object.
Any idea what I am doing wrong?
The username and password I have used has full SharePoint privileges.
I am using Visual Studio 2013, C#, .NET 4.0, and SharePoint 2010.
To fetch the title of the site your just need the value of the variable web.title.
namespace TestSharepoint
{
public class SharepointHelper
{
private ClientContext clientContext;
private Web rootWeb;
public SharepointHelper(string url, string username, string password)
{
clientContext = new ClientContext(url);
var credentials = new NetworkCredential(username, password, "oshirowanen.com");
clientContext.Credentials = credentials;
rootWeb = clientContext.Web;
clientContext.Load(rootWeb,web=>web.title);
clientContent.ExecuteQuery();
string siteTitle=web.title;
}
}
}