PublishingRolloutImage not persisting on Update(); - sharepoint

I have a list, that has three fields: Title, PublishingRollupImage and Description.
I want to upload the image to the library SiteCollectionImages and reference it on the list.
I'm able to upload the file to the folder SiteCollectionImages, and get it's url.
I'm also able to insert the item in the list "MyList", but the PublishingRolloutImage won't persist after the Update() method. I already tried to set the constructor for the ImageFieldValue, like this:
new ImageFieldValue("<img src='test.jpg' />");
but it didn't work.
Here's my code:
using (var site = new SPSite(SPContext.Current.Site.ID))
using (var web = site.OpenWeb())
{
var folder = web.GetFolder("SiteCollectionImages");
var file = folder.Files.Add(fileName, file, true);
folder.Update();
var list = web.Lists["MyList"];
var item = list.Items.Add();
item["Title"] = "MyItemTitle";
item["PublishingRollupImage"] = new ImageFieldValue { ImageUrl = file.Url };
item["Description"] = "MyDescription";
item.Update();
}
What i'm doing wrong?

After a lot of trial and error, i found out that i was doing two things wrong:
this:
item["PublishingRollupImage"] = new ImageFieldValue { ImageUrl = file.Url };
was supposed to be like this:
var image = item["PublishingRollupImage"] as ImageFieldValue ?? new ImageFieldValue();
image.ImageUrl = String.Format("/{0}", file.Url);
item["PublishingRollupImage"] = image;
and file.Url needs to start with a slash. If it doesn't start with a slash, it will break after the Update(); method. That's the reason for the String.Format up there.

Related

SharePoint userProfileProperties JSOM (JavaScript Object Model)

I am tryin to get some info from PeopleManager.getMyProperties() function.
I get the object,some values are null.when i check it from User Profile from Management,I can see the value. How can i fix this one ?
There is my working code to get object.
Note : I want to access Custom Property from User Profile which I created before.
I can see the property in the object but value is not coming.
Thank You All..
$(document).ready(function(){
SP.SOD.executeOrDelayUntilScriptLoaded(loadUserData, 'SP.UserProfiles.js');
});
var userProfileProperties;
function loadUserData(){
//Get Current Context
var clientContext = new SP.ClientContext.get_current();
//Get Instance of People Manager Class
var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
//Get properties of the current user
userProfileProperties = peopleManager.getMyProperties();
clientContext.load(userProfileProperties);
//Execute the Query.
clientContext.executeQueryAsync(onSuccess, onFail);
}
function onSuccess() {
console.log(userProfileProperties)
}
function onFail(sender, args) {
console.log("Error: " + args.get_message());
}
Try the below code and let me know. It works fine for me. I have passed the user name instead of My account. So that you can pass any user account here.
function getUserProperties(userName) {
var clientContext = new SP.ClientContext.get_current();
var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
var profilePropertyNames = ["FirstName", "LastName", "CustomProperty"]; //Have to load all the needed properties here
var targetUser = userName.trim();
var userProfilePropertiesForUser = new SP.UserProfiles.UserProfilePropertiesForUser(clientContext, targetUser, profilePropertyNames);
userProfileProperties = peopleManager.getUserProfilePropertiesFor(userProfilePropertiesForUser);
clientContext.load(userProfilePropertiesForUser);
clientContext.executeQueryAsync(onSuccess, onFail);
}
function onSuccess() {
// userProfileProperties result index is same as the properties loaded above
var firstName=userProfileProperties[0];
var lastName=userProfileProperties[1];
var customprop=userProfileProperties[2];
}
Mark it as answer if it helps.
I forget to write the solution,sorry for that one.
I tried the code which written by #NaveenPrasath. It is giving a lot of fields but it didn't return "Custom Prop Field".
Working code is shown below.
function getUserProperties(targetUser) {
var clientContext = new SP.ClientContext.get_current();
var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
personProperties = peopleManager.getPropertiesFor(targetUser);
clientContext.load(personProperties);
clientContext.executeQueryAsync(onRequestSuccess, onRequestFail);
}
function onRequestSuccess() {
var fullName = personProperties.get_userProfileProperties()['CustomPropField'];
}

Suitescript Code stops for no apparent Reason

I have the following code which executes a search, then just stops.
for (var i=1; i<=numberItems; i++ ) {
nlapiInsertLineItem(SUBLIST_Items,1);
var itemID = vendorItems[i].getId();
nlapiSetCurrentLineItemValue(SUBLIST_Items,'custrecordvpri_item',itemID );
var avgCost = Round(nlapiLookupField(itemType,itemID,'averagecost'),4);
var stdCost = Round(nlapiLookupField(itemType,itemID,'custitem_costrepl'),4);
var lastCost = Round(nlapiLookupField(itemType,itemID,'lastpurchaseprice'),4);
if (isNaN(avgCost)) { avgCost = '' };
if (isNaN(stdCost)) { stdCost = '' };
if (isNaN(lastCost)) { lastCost = '' };
nlapiSetCurrentLineItemValue(SUBLIST_Items,'custrecordvpri_costavg', avgCost );
nlapiSetCurrentLineItemValue(SUBLIST_Items,'custrecordvpri_costlast', lastCost );
nlapiSetCurrentLineItemValue(SUBLIST_Items,'custrecordvpri_coststd', stdCost );
nlapiSetCurrentLineItemValue(SUBLIST_Items,'custrecordvpri_vendorcurrency',vendorItems[i].getValue('vendorpricecurrency'));
nlapiSetCurrentLineItemValue(SUBLIST_Items,'custrecordvpri_currentprice',vendorItems[i].getValue('vendorcost'));
nlapiCommitLineItem(SUBLIST_Items);
}
It is all running as a client script, triggered by a button on the supplier record.
There are some sub functions within this functon (ie. a search etc...).
I cannot find a reason why the code would stop.
if I comment out the "while" loop, it executes the new window etc... and the main record (VprRecord) is created, but with no sublist items.
Is there something I'm missing here?? I'm not an experienced JS programmer, but the basics are there. Is there a limited number of nested functions permitted or something like that?
I only have the one record creation, so governance shouldn't be an issue.
Adding my search function which returns the search result object:
function getVendorItems(vendorid) {
try {
var filters = new Array();
var columns = new Array();
filters[0] = new nlobjSearchFilter('vendorcost', null, 'greaterthan', 0);
filters[1] = new nlobjSearchFilter('internalid', 'vendor', 'anyof', vendorid );
columns[0] = new nlobjSearchColumn('itemid');
columns[1] = new nlobjSearchColumn('entityid', 'vendor');
columns[2] = new nlobjSearchColumn('vendorcost');
columns[3] = new nlobjSearchColumn('vendorcode');
columns[4] = new nlobjSearchColumn('vendorpricecurrency');
//columns[5] = new nlobjSearchColumn('preferredvendor');
var searchresults = nlapiSearchRecord('item', null, filters, columns );
return searchresults;
} catch (err) { logError(err,'VPR_getVendorItems: (Vendor: '+vendorid+')' ) }
}
The code does not execute because there are unhandled javascript errors.
put your code in try catch block and on error log on console eg:
try { ...} catch(e){console.dir(e);}
Use browser's console using F12 to see the error
Also, make sure that you operate on searchResults as array not nlobjSearchResult

How to add a Web Part into a SitePages/Home.aspx using CSOM

has anyone managed to add a Web Part into a Wiki page using CSOM?
Background: Home.aspx is a Wiki page and all its WPs are located in the rich text zone (in fact a "WikiField" column). Technically they are located in a hidden "wpz" web part zone and in addition to this there is always a placeholder with WP's ID in the WikiField column.
I've modified the existing server-side code seen on http://blog.mastykarz.nl/programmatically-adding-web-parts-rich-content-sharepoint-2010/ and http://640kbisenough.com/2014/06/26/sharepoint-2013-moving-webparts-programmatically-to-rich-content-zone/ into this:
using System;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.WebParts;
public class Class1
{
void DeployWebPart(ClientContext clientContext, string zone, string pattern, string position)
{
List library = clientContext.Web.GetList("/sites/site/SitePages/");
clientContext.Load(library);
clientContext.ExecuteQuery();
CamlQuery query = CamlQuery.CreateAllItemsQuery(100);
ListItemCollection itemColl = library.GetItems(query);
clientContext.Load(itemColl, items => items.Include(i => i.Id, i => i.DisplayName, i => i["WikiField"]));
clientContext.ExecuteQuery();
ListItem item = itemColl.Where(i => i.DisplayName == "Home").First();
clientContext.ExecuteQuery();
File page = item.File;
LimitedWebPartManager lwm = page.GetLimitedWebPartManager(PersonalizationScope.Shared);
string xmlWebPart = #"<webParts>...</webParts>";
WebPartDefinition wpd = lwm.ImportWebPart(xmlWebPart);
WebPartDefinition realWpd = lwm.AddWebPart(wpd.WebPart, "wpz", 0);
List targetList = clientContext.Web.GetList("/sites/site/Announcements/");
clientContext.Load(targetList, l => l.Views);
clientContext.Load(realWpd);
clientContext.ExecuteQuery();
string wpId = String.Format("g_{0}", realWpd.Id.ToString().Replace('-', '_'));
if (zone == "wpz")
{
string htmlcontent = String.Format(CultureInfo.InvariantCulture, "<div class=\"ms-rtestate-read ms-rte-wpbox\" contenteditable=\"false\"><div class=\"ms-rtestate-notify ms-rtestate-read {0}\" id=\"div_{0}\"></div><div id=\"vid_{0}\" style=\"display:none;\"></div></div>", new object[] { realWpd.Id.ToString("D") });
string content = item["WikiField"] as string;
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(System.Text.RegularExpressions.Regex.Escape(pattern));
if (position == "before")
{
content = regex.Replace(content, (htmlcontent + pattern), 1);
}
else
{
content = regex.Replace(content, (pattern + htmlcontent), 1);
}
item.Update();
clientContext.ExecuteQuery();
}
}
}
Everything works fine until the last item.Update() and clientContext.ExecuteQuery() are being invoked. Before the Update() the new placeholder gets properly inserted into the WikiField contents. But after the Update() the WikiField contents reverts back to its original state (!)
Note: As an alternative it is possible to add the WP into another zone (eg. "Bottom"). In this case the WP gets displayed on the page. But it has two major drawbacks: The newly created zone is not well formatted and the WP cannot be moved or even deleted.
Thanks for any input on this.
The following example demonstrates how to add web part into Enterprise Wiki page:
public static void AddWebPartIntoWikiPage(ClientContext context, string pageUrl, string webPartXml)
{
var page = context.Web.GetFileByServerRelativeUrl(pageUrl);
var webPartManager = page.GetLimitedWebPartManager(PersonalizationScope.Shared);
var importedWebPart = webPartManager.ImportWebPart(webPartXml);
var webPart = webPartManager.AddWebPart(importedWebPart.WebPart, "wpz", 0);
context.Load(webPart);
context.ExecuteQuery();
string marker = String.Format(CultureInfo.InvariantCulture, "<div class=\"ms-rtestate-read ms-rte-wpbox\" contentEditable=\"false\"><div class=\"ms-rtestate-read {0}\" id=\"div_{0}\"></div><div style='display:none' id=\"vid_{0}\"></div></div>", webPart.Id);
ListItem item = page.ListItemAllFields;
context.Load(item);
context.ExecuteQuery();
item["PublishingPageContent"] = marker;
item.Update();
context.ExecuteQuery();
}
Usage
var webPartXml = System.IO.File.ReadAllText(filePath);
using (var ctx = new ClientContext(webUri))
{
AddWebPartIntoWikiPage(ctx, wikiPageUrl,webPartXml);
}
Result

Loading itemTemplate for WinJS.UI.ListView from external source

I am wondering if someone can shed some light on why this does not work.
I can successfully dynamically template each WinJS.UI.ListView item if I define the templates in my html view (First Scenario). However if I load the template from a seperate html file using a $.get statement it does not work (Second Scenario).
self.selectTemplate = function (itemPromise) {
return itemPromise.then(function (item) { ...
First Scenario:
(var itemTemplate = document.getElementById(item.data.controlType + "ItemTemplate");
var container = document.createElement("div");
itemTemplate.winControl.render(item.data, container);
return container;)
Second Scenario:
(var itemTemplatePromise = ko.bindingHandlers.searchPropertyBuilder.loadTemplate(item.data.controlType);
itemTemplatePromise.done(function (itemTemplateLoaded) {
var templateContainer = document.createElement("div");
templateContainer.innerHTML = itemTemplateLoaded;
templateElement = templateContainer.firstChild;
WinJS.UI.process(templateElement);
var container = document.createElement("div");
templateElement.winControl.render(item.data, container);
return container;
});)
}
WinJS.Utilities.markSupportedForProcessing(self.selectTemplate);
WinJS.Namespace.define("TemplateSelector", {
template: self.selectTemplate
});
I can see one bug in the code. but not sure if that is the only issue here. promises needs to be chained. winjs.ui.processAll returns a promise.
itemTemplatePromise.then(function (itemTemplateLoaded) {
var templateContainer = document.createElement("div");
templateContainer.innerHTML = itemTemplateLoaded;
templateElement = templateContainer.firstChild;
return WinJS.UI.processAll(templateElement);
}).then(function onprocessall()
{
var container = document.createElement("div");
templateElement.winControl.render(item.data, container);
return container;
});

Bast Way On Passing Query Parameters to Solrnet

I have been working on making a Search using Solrnet which is working the way I want to. But I just would like some advice on the best way to pass my query parameters from my web page into Solrnet.
What I would ideally like to do is pass my query string parameters similar to how this site does it: http://www.watchfinder.co.uk/SearchResults.aspx?q=%3a&f_brand=Rolex&f_bracelets=Steel&f_movements=Automatic.
As you can see from the sites query string it looks like it is being passed into SolrNet directly. Here is I am doing it at the moment (facet query segment):
public class SoftwareSalesSearcher
{
public static SoftwareSalesSearchResults Facet()
{
ISolrOperations solr = SolrOperationsCache.GetSolrOperations(ConfigurationManager.AppSettings["SolrUrl"]);
//Iterate through querystring to get the required fields to query Solrnet
List queryCollection = new List();
foreach (string key in HttpContext.Current.Request.QueryString.Keys)
{
queryCollection.Add(new SolrQuery(String.Format("{0}:{1}", key, HttpContext.Current.Request.QueryString[key])));
}
var lessThan25 = new SolrQueryByRange("SoftwareSales", 0m, 25m);
var moreThan25 = new SolrQueryByRange("SoftwareSales", 26m, 50m);
var moreThan50 = new SolrQueryByRange("SoftwareSales", 51m, 75m);
var moreThan75 = new SolrQueryByRange("SoftwareSales", 76m, 100m);
QueryOptions options = new QueryOptions
{
Rows = 0,
Facet = new FacetParameters {
Queries = new[] { new SolrFacetQuery(lessThan25), new SolrFacetQuery(moreThan25), new SolrFacetQuery(moreThan50), new SolrFacetQuery(moreThan75) }
},
FilterQueries = queryCollection.ToArray()
};
var results = solr.Query(SolrQuery.All, options);
var searchResults = new SoftwareSalesSearchResults();
List softwareSalesInformation = new List();
foreach (var facet in results.FacetQueries)
{
if (facet.Value != 0)
{
SoftwareSalesFacetDetail salesItem = new SoftwareSalesFacetDetail();
salesItem.Price = facet.Key;
salesItem.Value = facet.Value;
softwareSalesInformation.Add(salesItem);
}
}
searchResults.Results = softwareSalesInformation;
searchResults.TotalResults = results.NumFound;
searchResults.QueryTime = results.Header.QTime;
return searchResults;
}
}
At the moment I can't seem to see how I can query all my results from my current code by add the following querystring: q=:.
I'm not sure what you mean by "parameters being passed into SolrNet directly". It seems that watchfinder is using some variant of the model binder included in the SolrNet sample app.
Also take a look at the controller in the sample app to see how the SolrNet parameters are built.

Resources