SPNavigationNode.IsVisible property not working in sharepoint as expected - c#

I want to hide a quick launch node in a sharepoint site, but it's not working as expected. :(
My code is as under:
using (SPSite spSiteTest = new SPSite(serverUrl))
{
using (SPWeb mySite = spSiteTest.OpenWeb())
{
SPNavigationNodeCollection quickLaunchNodes = mySite.Navigation.QuickLaunch;
SPNavigationNode navQuickNode = new SPNavigationNode("Title", "www.stackoverflow.com", true);
foreach (SPNavigationNode node in quickLaunchNodes)
{
if (node.Title == navQuickNode.Title)
{
node.Url = navQuickNode.Url;
node.IsVisible = isVisible;
node.Update();
//mySite.Update();
return;
}
}
quickLaunchNodes.AddAsFirst(navQuickNode);
}
}
Am I missing something or is it a bug?

You can delete the nodes like this:
node.Delete();
mySite.Update();
or check the ExcludeFromNavigation method mentioned in this post (its author suggests that not being able to hide a navigation node by setting IsVisible to false is a SharePoint bug, too).

How to show/hide navigation nodes using SharePoint Server Side Object Model (SSOM)
PortalNavigation Class exposes the following methods for that purpose:
PortalNavigation.ExcludeFromNavigation - explicitly excludes a
specific subsite or page from being displayed in navigation
PortalNavigation.IncludeInNavigation - Explicitly includes a
specific subsite or page for display in navigation
Examples
How to hide site from Current navigation:
using (var site = new SPSite(siteUrl))
{
using (var web = site.OpenWeb())
{
var subWeb = web.Webs["Announcements"];
var publishingWeb = PublishingWeb.GetPublishingWeb(web);
publishingWeb.Navigation.ExcludeFromNavigation(false,subWeb.ID);
publishingWeb.Update();
}
}
How to show/hide navigation nodes using SharePoint Client Side Object Model (CSOM)
It is not supported to modify navigation settings via SharePoint CSOM.
Regarding SharePoint 2013:
In SharePoint 2013 was introduced a new
Microsoft.SharePoint.Client.Publishing and
Microsoft.SharePoint.Client.Publishing.Navigation namespaces in CSOM
API. But unfortunately it is not supported to modify navigation
settings using WebNavigationSettings class since properties are
exposes as a read-only.
For CSOM, you could utilize the ClientPortalNavigation.cs class that represents a CSOM counterpart for SSOM PortalNavigation Class. Follow Access and Manipulate Navigation Settings via SharePoint Client Object Model post for more details.
Examples
How to hide a page from Global navigation:
using (var ctx = new ClientContext(webUri))
{
//Get page file
var pageFile = ctx.Web.GetFileByServerRelativeUrl("/news/Pages/Announcements.aspx");
ctx.Load(pageFile);
ctx.ExecuteQuery();
//Hide page from Global navigation
var navigation = new ClientPortalNavigation(ctx.Web);
navigation.ExcludeFromNavigation(true, pageFile.UniqueId);
navigation.SaveChanges();
}
How to hide a site from Global navigation:
using (var ctx = new ClientContext(webUri))
{
//Get sub site
var result = ctx.LoadQuery(ctx.Web.Webs.Where(w => w.Title == "Archive"));
ctx.ExecuteQuery();
var subWeb = result.FirstOrDefault();
//Hide web from Global navigation
var navigation = new ClientPortalNavigation(ctx.Web);
navigation.ExcludeFromNavigation(true, subWeb.Id);
navigation.SaveChanges();
}

Related

Fatest way to check and create folder in document library within SharePoint Online (CSOM)?

I have a SharePoint Online where I can connect through my console application successfully:
private static ClientContext GetUserContext()
{
var o365SecurePassword = new SecureString();
foreach (char c in o365Password)
{
o365SecurePassword.AppendChar(c);
}
var o365Credentials = new SharePointOnlineCredentials(o365Username, o365SecurePassword);
var o365Context = new ClientContext(o365SiteUrl);
o365Context.Credentials = o365Credentials;
return o365Context;
}
But what I need now to do is to go into my SharePoint Document Library named "doc_archive" and check if there exists a folder with name "K20170409-01".
If not create a new one.
Failed Attempt
ClientContext context = GetUserContext();
Web web = context.Web;
Web webroot = context.Site.RootWeb;
context.Load(web);
context.Load(webroot);
List list = webroot.GetList("doc_archive");
context.Load(list);
FolderCollection folders = list.RootFolder.Folders;
context.Load(folders);
IEnumerable<Folder> existingFolders = context.LoadQuery(
folders.Include(
folder => folder.Name)
);
context.ExecuteQuery();
What is the fastest ways to check and create a folder within a document library in SharePoint Online via CSOM (commandline application)?
If you are happy with using external libraries then the OfficeDevPnP.Core has some great CSOM extensions for SharePoint and SharePoint Online. It's readily available as a NuGet package to add to your projects.
For your requirment there is the EnsureFolderPath extension. This function will check if a folder exists, create it if needed and return the Microsoft.SharePoint.Client.Folder object.
Very easy to use:
var webRelativeUrlToFolder = "/doc_archive/K20170409-01"
var folder = cc.Web.EnsureFolderPath(webRelativeUrlToFolder);
cc.Load(folder);
cc.ExecuteQuery();
I can't vouch for how fast this would be, but it works in the end on 0365. Note that it throws a ServerException if the target already exists.
using (var ctx = new ClientContext(siteUrl))
{
ctx.Credentials = new SharePointOnlineCredentials(username, securePwd);
var list = new ListCreationInformation()
{
Title = title
Description = "User Created Document Library",
TemplateType = asDocumentLibrary ? 101 : 100 // 100 is a custom list.
};
ctx.Web.Lists.Add(list);
ctx.ExecuteQuery();
success = true;
}
Most CSOM examples are found in Powershell. The process in C# CSOM is actually the same, so next time find a Powershell example when a C# one is not available.

Not able to hide set area using C# Code

We are not able to hide the SET area that is displayed in top navigation bar, I am using the below code snippet to achieve the same. But the subsite is not getting hidden even when the code is not throwing any error. Bit clueless as after unsafe update the code is functioning as expected.
Code Snippet:
using (SPSite siteCollection = new SPSite("http://****:****/VijaiTest/"))
{
using (SPWeb web = siteCollection.RootWeb)
{
PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
// Global Navigation
//Show Subsites
publishingWeb.Navigation.GlobalIncludeSubSites = false;
//Show Pages
publishingWeb.Navigation.GlobalIncludePages = false;
// Maximum number of dynamic items to show within this level of navigation:
publishingWeb.Navigation.GlobalDynamicChildLimit = 60;
publishingWeb.IncludeInCurrentNavigation = false;
web.AllowUnsafeUpdates = true;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//Update the changes
publishingWeb.Update();
});
}
}
I see a few potential problems with your code...
1. Don't wrap SPWeb web = sitecollection.RootWeb in a Using statement
While normally it's good practice to wrap SPSite and SPWeb objects in Using statements to ensure that they're disposed of properly, the SPSite.RootWeb property is an exception to this rule. The root web is disposed automatically along with the SPSite object, when it is disposed. Since you have SPSite siteCollection = new SPSite(... wrapped in a Using statement, you don't need to worry about disposal of the RootWeb.
Trying to dispose of the root web twice will add errors to your logs and can cause problems when accessing that web object programmatically.
2. Instantiate your SPSite and SPWeb objects inside your SPSecurity.RunWithElevatedPrivileges delegate
For SPSecurity.RunWithElevatedPrivileges to be effective, you must retrieve or create your SPSite and SPWeb objects within the delegate function.
Your code obtains the SPSite and SPWeb objects prior to running RunWithElevatedPrivileges, so any operations on those objects will run under the context of the current user instead of running with elevated privileges.
3. Check to be sure the SPWeb object is a valid PublishingWeb before executing GetPublishingWeb(web)
From Microsoft:
Before you use this method, check the IsPublishingWeb method to confirm that publishing behavior is supported on this instance of the SPWeb class. If publishing is not supported on the SPWeb, then the methods and properties of the PublishingWeb wrapper may behave unexpectedly.
After those changes, your code would look like this:
SPSecurity.RunWithElevatedPrivileges(delegate() {
using(SPSite siteCollection = new SPSite("http://****:****/VijaiTest/")) {
SPWeb web = siteCollection.RootWeb;
if(PublishingWeb.IsPublishingWeb(web)){
PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
// Don't show Subsites
publishingWeb.Navigation.GlobalIncludeSubSites = false;
// Don't show Pages
publishingWeb.Navigation.GlobalIncludePages = false;
// Maximum number of dynamic items to show within this level of navigation:
publishingWeb.Navigation.GlobalDynamicChildLimit = 60;
publishingWeb.IncludeInCurrentNavigation = false;
web.AllowUnsafeUpdates = true;
//Update the changes
publishingWeb.Update();
}else{
throw new Exception("Web is not a publishing web");
}
}
});

SPMeta2 System.InvalidCastException while trying to deploy model

I am currently trying to create a simple list in Sharepoint 365, using SPMeta2 framework. I have tried doing it according to the documentation, and got an exception, then I've decided to simply copy code from their samples, located here Now, when I'm trying to deploy my model I keep getting System.InvalidCastException. It says it needs SiteModelHost, but when I give it SiteModelHost I get same exception, saying WebModelHost. Obviously, when I give it web it asks for site. I would be grateful for any pointers.
Here is my code for deploying the model:
class Program
{
static void Main (string[] args)
{
var targetSite = new Uri("https://url.com/");
var login = "***.com";
var password = "1234";
var securePassword = new SecureString();
foreach (char c in password)
{
securePassword.AppendChar(c);
}
var onlineCredentials = new SharePointOnlineCredentials(login, securePassword);
var model = SPMeta2Model
.NewSiteModel(site =>
{
site
.WithFields(fields =>
{
fields
.AddField(FieldModels.Contact)
.AddField(FieldModels.Details);
})
.WithContentTypes(contentTypes =>
{
contentTypes
.AddContentType(ContentTypeModels.CustomItem)
.AddContentType(ContentTypeModels.CustomDocument);
})
.WithLists(lists =>
{
lists
.AddList(ListModels.TestLibrary)
.AddList(ListModels.TestList)
.AddList(ListModels.TestLinksList);
});
});
using (var context = new ClientContext(targetSite))
{
context.Credentials = onlineCredentials;
var povisionService = new CSOMProvisionService();
povisionService.DeployModel(WebModelHost.FromClientContext(context), model); // WebModelHost/SiteModelHost - same exception
}
Easy.
SPMeta2 allows to several types of models.
Site model reflects and contains all artefacts which could be deployed at site level - site features, custom actions, site fields, content types and so on.
Site model should be deployed within 'site model host'.
Web model reflects and contains all artefacts which could be deployed at web level - web features, lists, list views and so on.
Web model should be deployed within 'web model host'.
With CSOM provision, SiteModelHost.FromClientContext(context) and WebModelHost.FromClientContext(context) should be used to push site or web model accordingly.
Here is a working code for site model.
We removed lists (they belong to web) and use SiteModelHost.
var siteModel = SPMeta2Model
.NewSiteModel(site =>
{
site
.WithFields(fields =>
{
fields
.AddField(FieldModels.Contact)
.AddField(FieldModels.Details);
})
.WithContentTypes(contentTypes =>
{
contentTypes
.AddContentType(ContentTypeModels.CustomItem)
.AddContentType(ContentTypeModels.CustomDocument);
});
});
using (var context = new ClientContext(targetSite))
{
var povisionService = new CSOMProvisionService();
povisionService.DeployModel(SiteModelHost.FromClientContext(context), siteModel);
}
And the web model here.
We removed fields/content types, and use only lists plus WebModelHost.
var webModel = SPMeta2Model
.NewWebModel(web =>
{
web
.WithLists(lists =>
{
lists
.AddList(ListModels.TestLibrary)
.AddList(ListModels.TestList)
.AddList(ListModels.TestLinksList);
});
});
using (var context = new ClientContext(targetSite))
{
var povisionService = new CSOMProvisionService();
povisionService.DeployModel(WebModelHost.FromClientContext(context), webModel);
}
Finally, here are several links to get started:
Sample project at github
https://github.com/SubPointSolutions/spmeta2.contoso
SPMeta2 Yammer Group
http://yammer.com/spmeta2feedback
Some documentation (work in progress)
http://docs.subpointsolutions.com/spmeta2
Let me know how it goes, and if you need further assistance.
Cheers!

How to programmatically retrieve SharePoint My-Sites users' blog posts using C#?

I managed to access user profile content:
using (SPSite ospSite = new SPSite("http://localhost:80/"))
{
ServerContext s = ServerContext.GetContext(ospSite);
UserProfileManager profileManager = new UserProfileManager(s);
UserProfile p = profileManager.GetUserProfile("some_user");
// e.g. responsibility retrieval
var r = p["SPS-Responsibility"];
var responsibilities = r.GetTaxonomyTerms();
}
But I don't know how to access users' blog posts collection.
Any advice?
Use the PersonalSite property of UserProfile object to retrieve the user's My Site.
In the SPSite loop through, child SPWeb objects which are of template "Blog". Check out the templates names here:
http://blogs.msdn.com/b/richin/archive/2011/07/04/sharepoint-2010-site-template-names.aspx
Once you find the blog site, you can simply access the items in "Posts" List of the SPWeb object.

Sharepoint access to list ignore user permission

I created web part (something like wizard) and need change item value in list, but when get list item, they haven't items (logged user haven't access to this list). Can I ignore sharepoint permission, and update this value?
I use LINQ to sharepoint and get context:
using (SystemOcenContextDataContext ctx = new SystemOcenContextDataContext("http://sh2010/sites/270"))
{
// code :)
}
Update:
make test when get list using:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite ElevatedSite = new SPSite("http://sh2010/sites/270"))
{
using (SPWeb ElevatedWeb = ElevatedSite.OpenWeb())
{
list = ElevatedWeb.Lists["Ankiety i oceny"];
}
}
});
the object list "have" items
but in my project I use sharepoint linq datacontext when using:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SystemOcenContextDataContext ctx = new SystemOcenContextDataContext("http://sh2010/sites/270"))
{
item = ctx.AnkietyIOceny.First();
}
});
the context(ctx) didn't have any items :/
any idea?
SPSecurity.RunWithElevatedPrivileges(delegate()
{
// Pur your code here.
});
Get more details Here
The SharePoint linq provides doesn't work with ElevatedPrivileges. It accesses the SPWeb.Current instance which will have the access rights of the request and not the elevated user.
http://jcapka.blogspot.com/2010/05/making-linq-to-sharepoint-work-for.html
There's a work around, which I've implemented generally the same thing. It's a big awkward but it works as far as I can tell.

Categories