SPLimitedWebpartManager resetting custom web part properties on SaveChanges - sharepoint

We are running a SharePoint 2013 publishing site in 2010 mode. A section of the code which used to work fine in 2010 is not working after I installed the SharePoint 2013 CTP update (Configuration database version:
15.0.4815.1000).
I am trying to add a custom webpart with custom properties. The below code adds the webpart to the correct zone but when SPLimitedWebPartManager.SaveChanges(webpart) executes, it resets the custom property values to default values.
var wpManager = web.GetLimitedWebPartManager(page.ListItem.Url, System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared)
var dsWebPart = new DocumentSetBridge()
{
Title = "Shared Resource(s)",
ChromeType = System.Web.UI.WebControls.WebParts.PartChromeType.None,
KnowledgeCenterAssetsLibraryItemId = documentSetUniqueGuid,
ID = KnowledgeCenterSettings.DocumentSetBridgeWebPartId,
ShowManageDocLink = true,
IsUserCommunityDS = true
};
wpManager.AddWebPart(dsWebPart, UserGroupSettings.DOCUMENTSET_WEBPART_ZONE_ID, UserGroupSettings.DOCUMENTSET_WEBPART_ZONE_INDEX);
Any help is much appreciated. Thanks in advance.
Senthil S
UPDATE: Found the issue with permissions. It creates a new page with pre-defined webparts and assigns the user manage rights just for the page. Eventhough, the page is updated with proper permissions, it seems like SP is not recognizing it until sometime later. It could be because of some timing issue. If I add the web part impersonating as an admin everything looks fine.

After adding the WebPart to the SPLimitedWebPartManager you should do the following
wpManager.SaveChanges(dsWebPart);
web.Update();
and/or use SetPersonalizationDirty() like
dsWebPart.SetPersonalizationDirty();

Related

Unable to rename subsite URL via CSOM in SharePoint Online

I have set up a SharePoint Online site and I have created a provider hosted app. One of the features of the app is to create subsites and there are times when a subsite needs to be renamed, including renaming the subsite URL. I can use the CSOM to create the subsite without any problems but when I try to rename the URL I get an access denied error. If I only change the title and description of the subsite there is no problem. If I log into SharePoint Online via the browser (using the same user account!) and I use the UI to rename the URL then it works without any problem. The page in SharePoint I use to rename the URL is https://tenant.sharepoint.com/testproject/_layouts/15/prjsetng.aspx
I have tried this on both a Microsoft 365 Developer subscription (where I am doing most of my development and testing) and the main SharePoint Online site where the solution will eventually be deployed to. I don't know much of the details for the main SPO site, other people set it up and I was provided an account to test renaming the subsite. To be clear, I am able to rename the subsite URL via the UI in both the developer and main SharePoint Online sites.
Is there something I'm doing wrong? Is there a limitation to renaming a subsite URL via code in SharePoint Online? Is there a bug in SharePoint Online that prevents renaming a subsite URL using code?
The exception thrown includes ServerErrorTypeName = "Microsoft.SharePoint.SPException". I can get the correlation id but from what I understand that's of no use in SharePoint Online. The exception Message is literally "Access denied." There is no inner exception.
Here is the code I'm using to rename the subsite:
SharePointContext spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
ClientContext clientContext = new ClientContext(spContext.SPHostUrl)
{
Credentials = new SharePointOnlineCredentials("SPUserName", "SPPassword".ToSecureString())
};
var webUrl = request.OldProjectUrl;
var subweb = clientContext.Site.OpenWeb(webUrl);
clientContext.Load(subweb);
clientContext.ExecuteQuery();
subweb.Title = request.ProjectName;
subweb.Description = request.ProjectName;
subweb.ServerRelativeUrl = "/HardcodedForTesting"; // <-- if I skip this line there is no error
subweb.Update();
clientContext.ExecuteQuery();
I was trying to achieve the same result but encountered the same error.
I was able to solve this by disabling the NoScriptSite setting of the site collection.
Using the PnP.PowerShell module:
Set-PnPSite -NoScriptSite:$false
Also the value you give to the ServerRelativeUrl property must be correctly constructed. I found two allowed format:
/sites/site-collection-path/new-subsite-path
new-subsite-path
Just did a test on my environment, I could rename the subsite URL via CSOM code normally. I use the same code as yours.
For your issue, you'd better create a service request with Microsoft.

Automatically open Office documents on a Sharepoint Server 2013 in Firefox (full Office integration)

I recently switched to Firefox. Unfortunately my company still uses Sharepoint Server 2013 (migration to Sharepoint Online is planned somewhere in the future) which no longer offers a fluid integration with Office.
Every time I want to edit an Office document, it gets downloaded instead of being 'forwarded' to be opened by Word, Excel, etc. Modifications need to be saved locally and than uploaded afterwards. This is hugely annoying.
Is there some way that I can automate this in code, using a Firefox extension? Does Sharepoint expose some kind of hook or metadata containing the document's URL?
(Self-answer originally provided by Dotsoltecti; copied from question body into a proper answer).
Sharepoint 2013 passes the document's URL via the right-click contextual menu.
There exists a very neat add-on for Firefox called "custom right-click menu" by Sander Ronde. After installing this extension I added the script below:
var feedback = crmAPI.getClickInfo();
var url = feedback.linkUrl;
if (url.endsWith("docx") || url.endsWith("doc")) { var uri = "ms-word:ofe|u|" }
if (url.endsWith("xlsx") || url.endsWith("xls")) { var uri = "ms-excel:ofe|u|" }
if (url.endsWith("pptx") || url.endsWith("ppt")) { var uri = "ms-powerpoint:ofe|u|"}
var toOpen = uri.concat(url);
window.open(toOpen);
Et voilĂ : right clicking on a Word/Excel/PowerPoint-document executes the script and correctly forwards the document to the said program (you have to whitelist your SharePoint-site with the pop-up blocker). Modifications are handled directly by the Office-program.
Only drawback so far is that every time a document is opened, a new blank window is generated. I haven't found a solution for that yet, so suggestions are always welcome.

How do I "Follow Site" in Sharepoint 2013 with SSOM?

I haven't found that much information online about how to utilize the Social Part of SharePoint 2013 by Server Object Model. To understand and follow my question better i recommend you going to this site.
Lets say I have a Feature Receiver that is fired when i certain site is created and I would like to take advantage of the Follow Content Feature but instead of every time a site is created i would like to make the person that created the site automatically follow that site.
Does anyone got experience with working with the Social functionallity in SharePoint 2013? If so would be awesome with a summary how to use the different Social methods.
Social Actor
From what I've understood from reading about this you need to create a "Actor" to represent the item or in my case the site. SocialActorInfo which takes to properties ContentUri and ActorType.
SocialActorInfo actorInfo = new SocialActorInfo();
actorInfo.ContentUri = contentUrl;
actorInfo.ActorType = contentType;
Find and Check if that Actor is followed by the current user
Then you have to check if that SocialActor is Followed by the current user.
ClientResult<bool> isFollowed = followingManager.IsFollowed(actorInfo);
Follow/Unfollow the Site/Item
ClientResult<SocialFollowResult> result = followingManager.Follow(actorInfo);
clientContext.ExecuteQuery();
"followingManager.UnFollow(actorInfo);"
Questions,
If I want to follow a site, what kind of ActorTypes are there?
How do i do this with server-side code?
Additional Information
Microsoft says: When users follow documents, sites, or tags, status updates from documents, conversations on sites, and notifications of tag use show up in their newsfeed. The features related to following content can be seen on the Newsfeed and the Following content pages.
SharePoint Server 2013 provides the following APIs that you can use to programmatically follow content:
Client object models for managed code
NET client object model
Silverlight client object model
Mobile client object model
JavaScript object model
Representational State Transfer (REST) service
Server object model
Link to Follow Content in SharePoint 2013, I can just find how to do it with REST or CSOM.
Just wanted to Share, this Solved the task.
Just a Follow Method that takes a SPWeb object and a SPUser object.
SPServiceContext serverContext = SPServiceContext.GetContext(web.Site);
UserProfileManager profileManager = new UserProfileManager(serverContext);
string userString = user.LoginName.ToString();
UserProfile userProfile = profileManager.GetUserProfile(userString);
if (userProfile != null)
{
SPSocialFollowingManager manager = new
SPSocialFollowingManager(userProfile);
SPSocialActorInfo actorInfo = new SPSocialActorInfo();
actorInfo.ContentUri = new Uri(web.Url);
actorInfo.AccountName = user.LoginName;
actorInfo.ActorType = SPSocialActorType.Site;
manager.Follow(actorInfo);
}

SharePoint 2010 event handler (receiver) not working on personal sites of the MySites site collection

I have a SharePoint 2010 MySites set up on its own web application. There is the standard site collection at the base level, http://site:80/.
The personal sites for each user is at the managed URL /personal/.
I have a working event handler which add items to the Newsfeed when a user adds something to a picture library.
THE PROBLEM:
The problem is, this only works if they add to a picture library at the base site collection, http://site:80/, and does NOT work if they add to http://site:80/personal/last first/.
Does anyone know why? The event handler feature is site scoped and my understanding is that it should work on all subsites.
The problem is that personal sites are not subsites of My Site host. In fact each user's personal site is a site collection on its own. So basically you need to register your event receiver not only for My SIte host, but also for each user's personal site.
Ok. Because you can only 'staple' features to site definitions which will be provisioned in the future, you need a way to activate new features on existing sites.
So, the fix I discovered and used follows:
The default page for the newsfeed is http://site:80/default.aspx. If you create an event receiver and scope it for 'site' and deploy it globally or to that web application, then it will work on the base site collection. Each personal site is a site collection and has the feature but it needs to be activated on each personal site collection.
So, in the default.aspx page, you place the following which will activate the feature if it has not yet been activated.
<script runat="server" type="text/c#">
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
String sAccount = (((SPWeb)((SPSite)SPContext.Current.Site).OpenWeb()).CurrentUser.LoginName).Split('\\')[1];
String basePersonalURL = "http://site:80/personal/";
String eventReceiverFeatureId = "12345678-1234-1234-1234-1234567890ab";
using(SPSite site = new SPSite(basePersonalURL + sAccount)) {
site.AllowUnsafeUpdates = true;
using(SPWeb web = site.RootWeb) {
web.AllowUnsafeUpdates = true;
try { site.Features.Add(new Guid(eventReceiverFeatureId)); } catch {}
web.AllowUnsafeUpdates = false;
}
site.AllowUnsafeUpdates = false;
}
}
</script>
You also need to edit the web.config file in order to allow inline code to run for this page. Hope this helps.

How can I restrict what web parts show up in the Add Web Parts window?

I'd like to expose a web part to some users, but not all of them. How can I show or hide a web part in the Add Web Parts pop up window? I'd like to do this through code, and I'm hoping to use SharePoint Roles to make this happen.
I know you can manage which web parts show up in the Add Web Parts window in the Web Part Gallery.
While I haven't done it... since it's just another SharePoint List, you should be able to programmatically assign roles to Groups/Users?
More Info...
Update - Since you want to see some code. Nothing special, just a quick hack. You'll definitely want to do your standard error checking, etc. HTH :-)
using (SPSite site = new SPSite("YOUR SP URL"))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists["Web Part Gallery"];
// Your code for choosing which web part(s) to modify perms on
// will undoubtedly be more complex than this...
SPListItem listItem = list.GetItemById(19);
SPPrincipal groupToAdd = web.SiteGroups["YOUR GROUP NAME"] as SPPrincipal;
SPRoleAssignment newRoleAssignment = new SPRoleAssignment(groupToAdd);
SPRoleDefinition newRoleDefinition = web.RoleDefinitions["Read"];
newRoleAssignment.RoleDefinitionBindings.Add(newRoleDefinition);
listItem.RoleAssignments.Add(newRoleAssignment);
}
}
You can do this with SharePoint Groups.
Go to the Web Part Gallery, click "Edit" on the web part you wish to scope, then click Manage Permissions. Here you can specify which users or groups can use the web part.

Resources