Currently we are using modern team site and trying to add the add the object on the modern team site in SharePoint online
However we observed that we get Access denied error
We tried by setting the site property denyandaddcustomizedpages to false from powershell and it is working fine
However we are not able to get the code which can help us achieve the same using csom client side object model SharePoint online c#
Few articles mention try using pnp nugget but no code was able to find for the same
You can do that using the below sample code.
Do note, executing this code requires SharePoint admin privileges, do make the necessary modifications as per your requirements:
var tenantAdminSiteUrl = "https://tenant-admin.sharepoint.com";
var siteCollectionUrl = "https://tenant.sharepoint.com/sites/Test";
var userName = "admin#tenant.onmicrosoft.com";
var password = "password";
using (ClientContext clientContext = new ClientContext(tenantAdminSiteUrl))
{
SecureString securePassword = new SecureString();
foreach (char c in password.ToCharArray())
{
securePassword.AppendChar(c);
}
clientContext.AuthenticationMode = ClientAuthenticationMode.Default;
clientContext.Credentials = new SharePointOnlineCredentials(userName, securePassword);
var tenant = new Tenant(clientContext);
var siteProperties = tenant.GetSitePropertiesByUrl(siteCollectionUrl, true);
tenant.Context.Load(siteProperties);
tenant.Context.ExecuteQuery();
siteProperties.DenyAddAndCustomizePages = DenyAddAndCustomizePagesStatus.Disabled;
var operation = siteProperties.Update();
tenant.Context.Load(operation, op => op.IsComplete, op => op.PollingInterval);
tenant.Context.ExecuteQuery();
// this is necessary, because the setting is not immediately reflected after ExecuteQuery
while (!operation.IsComplete)
{
Thread.Sleep(operation.PollingInterval);
operation.RefreshLoad();
if (!operation.IsComplete)
{
try
{
tenant.Context.ExecuteQuery();
}
catch (WebException webEx)
{
// catch the error, something went wrong
}
}
}
}
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 have been really struggling with getting Access Tokens working with our Sharepoint site and still no luck.
The problem is when I access our site using the SharepointOnlineCredentials it works fine, well I can query the sharepoint as follows and this works but I want to use the new token stuff that just doesn't work for me
using (ClientContext context = new ClientContext(sharepointSiteUrl))
{
context.Credentials = GetCredentials();
var web = context.Web;
context.Load(web, w => w.Title);
context.ExecuteQuery();
if (context.Web.IsPropertyAvailable("Title"))
{
Console.WriteLine("Found title");
}
Console.WriteLine("Title: {0}", web.Title);
}
private static SharePointOnlineCredentials GetCredentials()
{
SecureString password = new SecureString();
foreach (char c in "MyPassword".ToCharArray()) password.AppendChar(c);
return new SharePointOnlineCredentials("myname#mycompany.com", password);
}
So now for the code that doesn't work
authContext = new AuthenticationContext(authority, new FileCache());
ClientCredential clientCredentials = new ClientCredential(clientId, clientSecret);
AuthenticationResult authenticationResult = authContext.AcquireToken(resource, clientCredentials);
Console.WriteLine("Token Type: {0} \nExpires: {1} \nToken: {2}", authenticationResult.AccessTokenType, authenticationResult.ExpiresOn, authenticationResult.AccessToken);
using (ClientContext context = TokenHelper.GetClientContextWithAccessToken(sharepointSiteUrl, authenticationResult.AccessToken))
{
var web = context.Web;
context.Load(web);
context.ExecuteQuery();
if (context.Web.IsPropertyAvailable("Title"))
{
Console.WriteLine("Found title");
}
Console.WriteLine("Title: {0}", web.Title);
}
Now when I run this the web.Title throws an error and the context.Web display 'Cannot find the method on the object instance.'
The web.Title in the debugger also states '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.'
I really would love some help with this as it's turned impossible for me. Thanks :)
Do I need to be aware or granting access somewhere else? as its strange that the first one works!
In the first example you are explicitly requesting the Title property from the CSOM end-point:
context.Credentials = GetCredentials();
var web = context.Web;
context.Load(web, w => w.Title); // explicitly requesting the Title property
context.ExecuteQuery();
Whereas in the second example there is no context.Load(web, w => w.Title);
Maybe this is the issue?
So I've looked at all the of the suggestions from the Linq to Twitter documentation regarding 401 statuses with Oauth and I honestly don't know what I'm doing wrong.
var auth = new PinAuthorizer
{
Credentials = new InMemoryCredentials
{
ConsumerKey = ConfigurationManager.AppSettings["twitterConsumerKey"],
ConsumerSecret = ConfigurationManager.AppSettings["twitterConsumerSecret"],
//OAuthToken = ConfigurationManager.AppSettings["twitterOAuthToken"], //don't include this
//AccessToken = ConfigurationManager.AppSettings["twitterAccessToken"] //or this for new users.
},
//
UseCompression = true,
GoToTwitterAuthorization = pageLink => Process.Start(pageLink),
GetPin = () =>
{
Console.WriteLine("/nAfter twitter authorizes your application you will be returned here or something/n");
Console.Write("Enter Pin here:");
return Console.ReadLine();
}
};
auth.Authorize();
using (var twitterCtx = new TwitterContext(auth, "https://api.twitter.com/1/",
"https://search.twitter.com/"))
{
try
{
twitterCtx.Log = Console.Out;
Console.WriteLine("Please provide tweet text");
string tweet = Console.ReadLine();
twitterCtx.UpdateStatus(tweet);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
I've ran this using the Pin Authentication method as well as the single user method (providing the oauth keys with config file). I'm able to query tweets but I can't update my status or send direct messages (I receive a 403 forbidden when I try to DM). I've provided a callback URL (albeit fake) so I can't think of why this isn't working. Any help would be appreciated.
PS this runs in Main, not sure if that matters
All you need is this overload of the TwitterContext ctor and it will use the proper base URLs:
new TwitterContext(auth)
The example you're using is for v1.0 URLs and LINQ to Twitter is on Twitter API v1.1 now. It will default to the proper base URLs.
If you're querying okay, but getting errors on update and DM, double check to make sure you aren't trying to tweet the same text. That's why I append a DateTime.Now to the end of test tweets - to guarantee uniqueness.