Showing up the image through code behind - sitecore

I have a sitecore control like this: <sc:Image ID="imgLogo" runat="server" Field="Image"/>
Now the current item does not have an Image field. I am pulling the Item through droptree in CurrentItem like this (GetFieldValue is same as GetField. I am overriding the base class in Sitecore):
string countryGuid = CurrentItem.GetFieldValue("Country", null);
Item country = sitecoreDatabase.GetItem(countryGuid);
BindCountryLogo();
Now in this Item I have an image for the country logo. All I want to show up on the sc:Image.
So far I got this:
private void BindCountryLogo(Item country)
{
Fields.ImageField logoField = country.Fields["Image"];
if (logoField != null && logoField.MediaItem != null)
{
//Sitecore.Data.Items.MediaItem image = new MediaItem(logoField.MediaItem);
//string src = Sitecore.Resources.Media.MediaManager.GetMediaUrl(image);
//imgLogo.DataSource = src;
//imgLogo.ImageUrl = logoField.MediaItem.Source.;
//string src = Sitecore.StringUtil.EnsurePrefix('/', Sitecore.Resources.Media.MediaManager.GetMediaUrl(logoField));
//Sitecore.Data.Items.MediaItem img = new MediaItem(ImageField.Medi)
}
}
None of them are working.

The control has a property "Item" which you can set to the item that holds the imageField.
Your BindCountryLogo should look like this:
private void BindCountryLogo(Item country)
{
imgLogo.Item = country;
}
(Or remove the BindCountryLogo() method and set the Item in the main method ;) )

Related

Display sitecore treelist selected in cshtml

Source Image
Display selected values in cshtml file
wrote this code but it's not working
List<Item> lstWellnessName = null;
Sitecore.Data.Fields.MultilistField WellnessList =
WellnessItem.Fields["Property Wellness"];
if (WellnessList != null && WellnessList.TargetIDs != null)
{
Item[] result = WellnessList.GetItems();
lstWellnessName = result.ToList();
}

set value in the droplink field

How do I assign values in a droplink through coding?
Sitecore.Data.Database master = Sitecore.Configuration.Factory.GetDatabase("master");
Sitecore.Data.Items.Item PriceBookHome = master.GetItem("/sitecore/content/Administration/Price Books/Clarisonic-us-retail");
string currency = "INR";
string currenySource = PriceBookHome.Fields["Currency"].Source;
Sitecore.Data.Items.Item currenyDictSource = master.GetItem(currenySource);
foreach (Item im in currenyDictSource.GetChildren())
{
if (im.Fields["Key"].Value == currency)
{
PriceBookHome.Editing.BeginEdit();
PriceBookHome.Fields["Currency"].SetValue(im.DisplayName, true);
PriceBookHome.Editing.EndEdit();
}
}
I am getting the following error on the droplink after insertion: "This field contains a value that is not in the selection list"
Error I am getting as follows:
droplink source[Currency path as given source in droplink]
You need to set the ID of the currency item as value, not the name.
PriceBookHome.Fields["Currency"] = im.ID.ToString();
Most likely it's because you're storing a string (the displayname) in the field.
As Ruud says, you can put the ID in, or do something like this:
PriceBookHome.Editing.BeginEdit();
var field = (Sitecore.Data.Fields.ReferenceField)PriceBookHome.Fields["Currency"];
field.TargetItem = im;
PriceBookHome.Editing.EndEdit();

Sitecore change rendering datasource

Hello I would like create special page for private use for where i will be have possibility to change data source value for each rendering item.
I have created next code, but it dos't save any changes to items.
SC.Data.Database master = SC.Configuration.Factory.GetDatabase("master");
SC.Data.Items.Item itm = master.GetItem(tbPath.Text);
if (itm != null)
{
// Get the sublayout to update
//string sublayout_name = txtSublayout.Text.Trim();
//if (!string.IsNullOrEmpty(sublayout_name))
{
// Get the renderings on the item
RenderingReference[] refs = itm.Visualization.GetRenderings(SC.Context.Device, true);
if (refs.Any())
{
//var data = refs.Select(d=>d);
//refs[0].Settings.DataSource
var sb = new StringBuilder();
using (new SC.SecurityModel.SecurityDisabler())
{
itm.Editing.BeginEdit();
foreach (var d in refs)
{
if (d.Settings.DataSource.Contains("/sitecore/content/Site Configuration/"))
{
var newds = d.Settings.DataSource.Replace("/sitecore/content/Site Configuration/", "/sitecore/content/Site Configuration/" + tbLanguage.Text + "/");
// sb.AppendLine(string.Format("{0} old: {1} new: {2}<br/>", d.Placeholder, d.Settings.DataSource, newds));
d.Settings.DataSource = newds;
}
}
itm.Editing.EndEdit();
}
//lblResult.Text = sb.ToString();
}
}
}
how I can change data source ?
thanks
You're mixing up two different things in Sitecore here.
The datasource that is assigned to a rendering at run-time, when Sitecore is rendering a page
The datasource that is assigned to the presentation details of an item
The simplest approach to achieve what I think you're trying to achieve, would be this.
Item itm = database.GetItem("your item");
string presentationXml = itm["__renderings"];
itm.Editing.BeginEdit();
presentationXml.Replace("what you're looking for", "what you want to replace it with");
itm.Editing.EndEdit();
(I've not compiled and run this code, but it should pretty much work as is)
You are not saving the changes to the field.
Use the LayoutDefinitation class to parse the layout field, and foreach all the device definition, and rendering definitions.
And finaly commit the LayoutDifinition to the layout field.
SC.Data.Items.Item itm = master.GetItem(tbPath.Text);
var layoutField = itm.Fields[Sitecore.FieldIDs.LayoutField];
LayoutDefinition layout = LayoutDefinition.Parse(layoutField.Value);
for (int i = 0; i < layout.Devices.Count; i++)
{
DeviceDefinition device = layout.Devices[i] as DeviceDefinition;
for (int j = 0; j < device.Renderings.Count; j++)
{
RenderingDefinition rendering = device.Renderings[j] as RenderingDefinition;
rendering.Datasource = rendering.DataSource.Replace("/sitecore/content/Site Configuration/",
"/sitecore/content/Site Configuration/" + tbLanguage.Text + "/");
}
}
itm.Editing.BeginEdit();
var xml =layout.ToXml()
layoutField.Value = xml;
itm.Editing.EndEdit();
The code is not testet, but are changed from something i have in production to replace datasources on a copy event
If any one looking for single line Linq : (Tested)
var layoutField = item.Fields[Sitecore.FieldIDs.LayoutField];
if (layoutField != null)
{
var layout = LayoutDefinition.Parse(layoutField.Value);
if (layout != null)
{
foreach (var rendering in layout.Devices.Cast<DeviceDefinition>()
.SelectMany
(device => device.Renderings.Cast<RenderingDefinition>()
.Where
(rendering => rendering.ItemID == "RenderingYoulooking")))
{
rendering.Datasource = "IDYouWantToInsert";
}
layoutField.Value = layout.ToXml();
}
}

How to get the large picture from feed with graph api?

When loading the Facebook feeds from one page, if a picture exist in the feed, I want to display the large picture.
How can I get with the graph API ? The picture link in the feed is not the large one.
Thanks.
The Graph API photo object has a picture connection (similar to that the user object has):
“The album-sized view of the photo. […] Returns: HTTP 302 redirect to the URL of the picture.”
So requesting https://graph.facebook.com/{object-id-from-feed}/picture will redirect you to the album-sized version of the photo immediately. (Usefull not only for displaying it in a browser, but also if f.e. you want to download the image to your server, using cURL with follow_redirect option set.)
Edit:
Beginning with API v2.3, the /picture edge for feed posts is deprecated.
However, as a field the picture can still be requested – but it will be a small one.
But full_picture is available as well.
So /{object-id-from-feed}?fields=picture,full_picture can be used to request those, or they can be requested directly with the rest of feed data, like this /page-id/feed?fields=picture,full_picture,… (additional fields, such as message etc., must be specified the same way.)
What worked for me :
getting the picture link from the feed and replacing "_s.jpg" with "_n.jpg"
OK, I found a better way. When you retrieve a feed with the graph API, any feed item with a type of photo will have a field called object_id, which is not there for plain status type items. Query the Graph API with that ID, e.g. https://graph.facebook.com/1234567890. Note that the object ID isn't an underscore-separated value like the main ID of that feed item is.
The result of the object_id query will be a new JSON dictionary, where you will have a source attribute containing a URL for an image that has so far been big enough for my needs.
There is additionally an images array that contains more image URLs for different sizes of the image, but the sizes there don't seem to be predictable, and don't all actually correspond to the physical dimensions of the image behind that URL.
I still wish there was a way to do this with a single Graph API call, but it doesn't look like there is one.
For high res image links from:
Link posts
Video posts
Photo posts
I use the following:
Note: The reason I give the _s -> _o hack precedence over the object_id/picture approach is because the object_id approach was not returning results for all images.
var picture = result.picture;
if (picture) {
if (result.type === 'photo') {
if (picture.indexOf('_s') !== -1) {
console.log('CONVERTING');
picture = picture.replace(/_s/, '_o');
} else if (result.object_id) {
picture = 'https://graph.facebook.com/' + result.object_id + '/picture?width=9999&height=9999';
}
} else {
var qps = result.picture.split('&');
for (var i = 0; i < qps.length; i++) {
var qp = qps[i];
var matches = qp.match(/(url=|src=)/gi);
if (matches && matches.length > 0) picture = decodeURIComponent(qp.split(matches[0])[1]);
}
}
}
This is a new method to get a big image. it was born after the previews method doesn't works
/**
* return a big url of facebook
* works onky for type PHOTO
* #param picture
* #param is a post type link
* #return url of image
*/
#Transactional
public String getBigImageByFacebookPicture(String pictrue,Boolean link){
if(link && pictrue.contains("url=http")){
String url = pictrue.substring(pictrue.indexOf("url=") + 4);
try {
url = java.net.URLDecoder.decode(url, "UTF-8");
} catch (UnsupportedEncodingException e) {
StringBuffer sb = new StringBuffer("Big image for Facebook link not found: ");
sb.append(link);
loggerTakePost.error(sb.toString());
return null;
}
return url;
}else{
try {
Document doc = Jsoup.connect(pictrue).get();
return doc.select("#fbPhotoImage").get(0).attr("src");
} catch (Exception e) {
StringBuffer sb = new StringBuffer("Big image for Facebook link not found: ");
sb.append(link);
loggerTakePost.error(sb.toString());
return null;
}
}
}
Enjoy your large image :)
Actually, you need two different solutions to fully fix this.
1] https://graph.facebook.com/{object_id}/picture
This solution works fine for images and videos posted to Facebook, but sadly, it returns small images in case the original image file was not uploaded to Facebook directly. (When posting a link to another site on your page for example).
2] The Facebook Graph API provides a way to get the full images in the feed itself for those external links. If you add 'full_picture' to the fields like in this example below when calling the API, you will be provided a link to the higher resolution version.
https://graph.facebook.com/your_facebook_id/posts?fields=id,link,full_picture,description,name&access_token=123456
Combining these two solutions I ended up filtering the input in PHP as follows:
if ( isset( $post['object_id'] ) ){
$image_url = 'https://graph.facebook.com/'.$post['object_id'].'/picture';
}else if ( isset( $post['full_picture'] ) ) {
$image_url = $post['full_picture'];
}else{
$image_url = '';
}
See: http://api-portal.anypoint.mulesoft.com/facebook/api/facebook-graph-api/docs/reference/pictures
Just put "?type=large" after the URL to get the big picture.
Thanks to #mattdlockyer for the JS solution. Here is a similar thing in PHP:
$posts = $facebook->api('/[page]/posts/', 'get');
foreach($posts['data'] as $post)
{
if(stristr(#$post['picture'], '_s.'))
{
$post['picture'] = str_replace('_s.', '_n.', #$post['picture']);
}
if(stristr(#$post['picture'], 'url='))
{
parse_str($post['picture'], $picturearr);
if($picturearr['url'])
$post['picture'] = $picturearr['url'];
}
//do more stuff with $post and $post['picture'] ...
}
After positive comment from #Lachezar Todorov I decided to post my current approach (including paging and using Json.NET ;):
try
{
FacebookClient fbClient = new FacebookClient(HttpContext.Current.Session[SessionFacebookAccessToken].ToString());
JObject posts = JObject.Parse(fbClient.Get(String.Format("/{0}/posts?fields=message,picture,link,attachments", FacebookPageId)).ToString());
JArray newsItems = (JArray)posts["data"];
List<NewsItem> result = new List<NewsItem>();
while (newsItems.Count > 0)
{
result.AddRange(GetItemsFromJsonData(newsItems));
if (result.Count > MaxNewsItems)
{
result.RemoveRange(MaxNewsItems, result.Count - MaxNewsItems);
break;
}
JToken paging = posts["paging"];
if (paging != null)
{
if (paging["next"] != null)
{
posts = JObject.Parse(fbClient.Get(paging.Value<String>("next")).ToString());
newsItems = (JArray)posts["data"];
}
}
}
return result;
}
And the helper method to retieve individual items:
private static IEnumerable<NewsItem> GetItemsFromJsonData(IEnumerable<JToken> items)
{
List<NewsItem> newsItems = new List<NewsItem>();
foreach (JToken item in items.Where(item => item["message"] != null))
{
NewsItem ni = new NewsItem
{
Message = item.Value<String>("message"),
DateTimeCreation = item.Value<DateTime?>("created_time"),
Link = item.Value<String>("link"),
Thumbnail = item.Value<String>("picture"),
// http://stackoverflow.com/questions/28319242/simplify-looking-up-nested-json-values-with-json-net/28359155#28359155
Image = (String)item.SelectToken("attachments.data[0].media.image.src") ?? (String)item.SelectToken("attachments.data[0].subattachments.data[0].media.image.src")
};
newsItems.Add(ni);
}
return newsItems;
}
NewsItem class I use:
public class NewsItem
{
public String Message { get; set; }
public DateTime? DateTimeCreation { get; set; }
public String Link { get; set; }
public String Thumbnail { get; set; }
public String Image { get; set; }
}

Opening Rich Text Editor in custom field of Sitecore Content Editor

I'm implementing a custom field in Sitecore for the Content Editor, and I need to be able to open the Rich Text editor and get the data from there. I'm not really sure where to look though, nor how to go about it.
Had to decompile the Sitecore.Kernel DLL in order to figure this out.
First thing is to spin off a call from the Context.ClientPage object
So, for my situation:
switch (message.Name)
{
case "richtext:edit":
Sitecore.Context.ClientPage.Start(this, "EditText");
break;
}
You will then need to have a method in your class with the same name as defined in the above Start method. Then, you either start the rich text control if the request isn't a postback, or handle the posted data
protected void EditText(ClientPipelineArgs args)
{
Assert.ArgumentNotNull(args, "args");
if (args.IsPostBack)
{
if (args.Result == null || args.Result == "undefined")
return;
var text = args.Result;
if (text == "__#!$No value$!#__")
text = string.Empty;
Value = text;
UpdateHtml(args); //Function that executes Javascript to update embedded rich text frame
}
else
{
var richTextEditorUrl = new RichTextEditorUrl
{
Conversion = RichTextEditorUrl.HtmlConversion.DoNotConvert,
Disabled = Disabled,
FieldID = FieldID,
ID = ID,
ItemID = ItemID,
Language = ItemLanguage,
Mode = string.Empty,
Source = Source,
Url = "/sitecore/shell/Controls/Rich Text Editor/EditorPage.aspx",
Value = Value,
Version = ItemVersion
};
UrlString url = richTextEditorUrl.GetUrl();
handle = richTextEditorUrl.Handle;
ID md5Hash = MainUtil.GetMD5Hash(Source + ItemLanguage);
SheerResponse.Eval("scContent.editRichText(\"" + url + "\", \"" + md5Hash.ToShortID() + "\", " +
StringUtil.EscapeJavascriptString(GetDeviceValue(CurrentDevice)) + ")");
args.WaitForPostBack();
}