Sitecore Select Media Dialog Buttons are not working properly? Here is Solution

Sitecore Select Media Dialog Buttons are not working properly? Here is Solution

scMedia

Our team upgraded one of project to Sitecore version 8.2. During testing phase a bug was logged saying that when click on “browse” button of image field “Select Media” speak dialog box opens, but buttons in the left  –

  • All image files
  • All video files
  • My images
  • Recently uploaded images
  • Recently uploaded video
  • Recently uploaded by me

were not working properly and not showing anything.

It was a big issue –

bug

Well Sitecore use different index configuration for the Speak content search. There are three config files for the speak content search according to the search provider –

  1. For Azure – Sitecore.Speak.ContentSearch.Azure.config.disabled
  2. For Lucene – Sitecore.Speak.ContentSearch.Lucene.config
  3. For Solr – Sitecore.Speak.ContentSearch.Solr.config.example

by default it will be enable for the lucene but in our case we were using Solr and we missed to enable the “Sitecore.Speak.ContentSearch.Solr.config” file. that was the cause of the problem.

bugkill

 

That’s it.

 

 

Advertisements
Convert Coveo Rest API JSON result into object using custom Deserialize

Convert Coveo Rest API JSON result into object using custom Deserialize

When we use the Coveo Rest API by passing parameters to get the results in JSON, it provides a lots of things in the results, and creating class and properties for all these result is a tedious work. And also in our case we don’t require all the result properties and creating multiple classes for the different value will make the thing complex. So we have decided to use Json to object converter, but problem arrives when we don’t know the properties returns in the result because result can return any type of sitecore page item. One solution we have use to create a Dynamic Json Converter. So how it is going to work? We got the result by making call to the coveo cloud and passing query and then we need to deserialize using the custom deserialize.

            var result = MakeCoveoRequest.MakeRequest(q);

var serializer = new JavaScriptSerializer();

serializer.RegisterConverters(new[] { new DynamicJsonConverter() });

dynamic obj = serializer.Deserialize(result, typeof(object));

we need to create as instance of the JavaScriptSerializer and then we need to registor the convertor with our custom dynamic Json convertor. Now the object of the JavaScriptSerializer will deserialize the result in dynamic object.

Our Custom DynamicJsonConverter will override default Deserialize function to convert the json into dictionary key value pair where key will be dynamic object property and value will be value or any dynamic object.

using System;

using System.Collections;

using System.Collections.Generic;

using System.Collections.ObjectModel;

using System.Dynamic;

using System.Linq;

using System.Text;

using System.Web.Script.Serialization;

 

namespace MyNameSpace

{

public class DynamicJsonConverter : JavaScriptConverter

{

public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)

{

if (dictionary == null)

throw new ArgumentNullException(“dictionary”);

 

return type == typeof(object) ? new DynamicJsonObject(dictionary) : null;

}

 

public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)

{

throw new NotImplementedException();

}

 

public override IEnumerable<Type> SupportedTypes

{

get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); }

}

 

#region Nested type: DynamicJsonObject

 

private sealed class DynamicJsonObject : DynamicObject

{

private readonly IDictionary<string, object> _dictionary;

 

public DynamicJsonObject(IDictionary<string, object> dictionary)

{

if (dictionary == null)

throw new ArgumentNullException(“dictionary”);

_dictionary = dictionary;

}

 

public override string ToString()

{

var sb = new StringBuilder(“{“);

ToString(sb);

return sb.ToString();

}

 

private void ToString(StringBuilder sb)

{

var firstInDictionary = true;

foreach (var pair in _dictionary)

{

if (!firstInDictionary)

sb.Append(“,”);

firstInDictionary = false;

var value = pair.Value;

var name = pair.Key;

if (value is string)

{

sb.AppendFormat(“{0}:\”{1}\””, name, value);

}

else if (value is IDictionary<string, object>)

{

new DynamicJsonObject((IDictionary<string, object>)value).ToString(sb);

}

else if (value is ArrayList)

{

sb.Append(name + “:[“);

var firstInArray = true;

foreach (var arrayValue in (ArrayList)value)

{

if (!firstInArray)

sb.Append(“,”);

firstInArray = false;

if (arrayValue is IDictionary<string, object>)

new DynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb);

else if (arrayValue is string)

sb.AppendFormat(“\”{0}\””, arrayValue);

else

sb.AppendFormat(“{0}”, arrayValue);

 

}

sb.Append(“]”);

}

else

{

sb.AppendFormat(“{0}:{1}”, name, value);

}

}

sb.Append(“}”);

}

 

public override bool TryGetMember(GetMemberBinder binder, out object result)

{

if (!_dictionary.TryGetValue(binder.Name, out result))

{

// return null to avoid exception.  caller can check for null this way…

result = null;

return true;

}

 

result = WrapResultObject(result);

return true;

}

 

public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)

{

if (indexes.Length == 1 && indexes[0] != null)

{

if (!_dictionary.TryGetValue(indexes[0].ToString(), out result))

{

// return null to avoid exception.  caller can check for null this way…

result = null;

return true;

}

 

result = WrapResultObject(result);

return true;

}

 

return base.TryGetIndex(binder, indexes, out result);

}

 

private static object WrapResultObject(object result)

{

var dictionary = result as IDictionary<string, object>;

if (dictionary != null)

return new DynamicJsonObject(dictionary);

 

var arrayList = result as ArrayList;

if (arrayList != null && arrayList.Count > 0)

{

return arrayList[0] is IDictionary<string, object>

? new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x)))

: new List<object>(arrayList.Cast<object>());

}

 

return result;

}

}

}

#endregion

}

Coveo Get Authentication key

Coveo Get Authentication key

In our pervious blog we were passing the authorization key in the header of the POST method for the authorization. This blog is a help guide to generate the API key from the Coveo Cloud Plateform. Here are the steps –

1. login into the platform.cloud.coveo.com/admin- It will show you the following UI, where in left side you will have search, analytics, and organization menus

coveologin

 

 

2  – Click on the API key menu under in the organization menu (it could be second last link). It will open a page where you can see existing API key’s Name, description, status, creation date and author of the key but you can’t see the actual key in this list.

apikey2

 

3 – Now click on the add key button on top right section of the api key page, it will open a pop up which will ask you about the configuration of the key such as Name, description, allowed and denied IPs if any.

APIKEY_3

 

You can also add the view, edit, enable privileges for the different search, analytics and organization services

APIKEY_priv.png

in the privilges please make sure to enable execute queries in search configuration seaction.

 

4 – After adding the configuration information click on the Add button at bottom right section of the page. It will open a dialog containing the API key

APIKEY_4

 

5 – Please make sure to copy the API key before closing the dialog, you will not able to see it again. this API key is your authorization key for the REST API authorization.

 

Coveo REST Search API Using Post Method

Coveo REST Search API Using Post Method

Coveo Rest API is a simple REST interface for invoking, exposing and manipulating the search based on the different filtering and search criteria.

Coveo provide both cloud and on-permises indexing Where Coveo cluod customer can accessed the REST API throught Coveo Cloud Plateform. But for on-permise indexing, we need to deploy the Search API locally. We are using the Coveo Cloud Platform and this blog is based on it. And when we are taking about the Coveo Cloud Platform then REST API is available to all users through a single URL – https://cloudplatform.coveo.com/rest/search/v2

Coveo provide many means of client authentication, but we will use the Authorization Key for the authenticating the client. We can perform both GET and POST method for the search. We can pass multiple supporting parameter either in the query string or in the body of the POST method as JSON format.

A typical POST method example in post man for the coveo cloud plateform is as follow –

postman

Where POST URL is https://cloudplatform.coveo.com/rest/search/v2, and authorization is done using Authentication key. Different parameters for the search such as organizationid, query, advance query etc. are passed in the body as content type – application/json.

A C# static class for making query to the coveo cloud plate form is as follow –

using System;

using System.IO;

using System.Net;

using System.Text;

using Sitecore.Diagnostics;

using MyStringExtentions

 

namespace MyNameSpace

{

Public static class MakeCoveoRequest

{

public static string MakeRequest(string query)

{

var result = string.Empty;

var CoveoRestUrl = “https://cloudplatform.coveo.com/rest/search/v2”;

 

var coveoUri = new Uri(CoveoRestUrl);

 

var httpWebRequest = WebRequest.Create(coveoUri) as HttpWebRequest;

if (httpWebRequest == null) return result;

 

try

{

var postData = Encoding.UTF8.GetBytes(query);

httpWebRequest.Method = “POST”;

httpWebRequest.PreAuthenticate = true;

httpWebRequest.Headers.Add(“Authorization”, “Bearer MyAuthorizationKey”);

httpWebRequest.ContentType = “application/json”;

httpWebRequest.ContentLength = postData.Length;

using (var dataStream = httpWebRequest.GetRequestStream())

{

dataStream.Write(postData, 0, postData.Length);

}

var myWebResponse = httpWebRequest.GetResponse();

var responseStream = myWebResponse.GetResponseStream();

if (responseStream == null) return null;

var myStreamReader = new StreamReader(responseStream, Encoding.Default);

result = myStreamReader.ReadToEnd();

responseStream.Close();

myWebResponse.Close();

}

catch (WebException ex)

{

Log.Error(“Message” + ex.Message, ex);

}

 

return result;

}

}

}

 

Thanks

 

Coveo for Sitecore : Intalligent Search for your website

Coveo for Sitecore : Intalligent Search for your website

Coveo is a provider of intelligent and predictive search technologies and as name says Coveo for sitecore is same for the Sitecore plateform. So what it offers? Well it makes your website more responsive, proactive and relevant for every visitor. it accesses site content and information, recommends the most relevant information and perform intelligent operation to improves results for future visits and visitors.

Let first understand the Architecture of Sitecore and Coveo with Sitecore. I have borrow following images from coveo’s developer site, where in first image you can see the basic architecture of sitecore

basic Sitecore architecture

And in second image – improve architecture of sitecore with coveo where each level have coveo block.

coveo improved sitecore architecture

Coveo installation – installation of coveo is easy and can be done by performing setups from below link –

https://developers.coveo.com/display/public/SitecoreV4/Setting+Up+Coveo+for+Sitecore

Coveo indexing – coveo provide both Cloud or On-Premises Indexes, on-permises is free edition where cloud provide one month trail. There are lots of advantage of using cloud indexing such as auto scaling, machine learning, security handling etc.

Coveo provides lots of out of box features which makes sitecore super powerful. A big rule engine provide more flexibility and power, supports MVC, provide REST API to make it plateform independent for the search. It also supports Linq API which makes backend user’s life easy.

There are lots of blog already on the Coveo about its introduction, setup and features, reason behind writing this blog is that, it is prologue for my next series of blogs.

Resolve XHTML markup is incorrect near placeholder “header” Error, only for “header” key

Resolve XHTML markup is incorrect near placeholder “header” Error, only for “header” key

Lets start with our problem,

We were facing a weird issue in experience editor, where we are getting following error –

enter image description here

XHTML markup is incorrect near placeholder “header”. For more information about this issue refer to Sitecore Knowledge base article https://kb.sitecore.net/articles/365101.

I know this error message shows when there some XHTML validation problem. But In our case its not related to XHTML validation.

What was weird!!!!!!

200

The weird thing here was that if I change my placeholder key “header” (i.e. – “Header” or “header1”) and update the presentation details, it resolve the problem. Don’t konw what is problem with “header” placeholder key. here the code we are using on layout –

@Html.Sitecore().Placeholder(“header”)

We were using Sitecore version – 8.2 update 2

I ask this question on Sitecore stackexchange (Link), but didn’t get any solution.

First solution I try was rebuilding indexes using the Indexing Manager from the Control Panel and check whether the issue is still reproducible. I did the same but it was still there.

It’s still reproducible after rebuilding the indexes becasue it was not related to indexing. I found the root cause of this problem and it was related to some jquery function, in the header html a section has id=”header” and some jquery functions are based on this id in a custom jquery file “jquery.layout.js”.

Since our placeholder key and the id jquery using was same. Then updated the id in both jquery and html and it resolve my problme every thing worked like a charm.

I ask question to sitecore support that what was wrong in this js file? and don’t you recommend to use placeholder key as id in html? I after a good discussion here is the moral of all story –

The issue may be caused by the behavior when a placeholder expands to a div with an id similar to its key. Thus, if you already have the same id in your markup, the validation error occurs. To avoid the issue please consider giving the unique key value to your placeholders (as for me (“me” and “I” here is sitecore support persoon), I create them with the ‘ph’ prefix, e.g. phMain, phContent).

and that’s it.

 

Send Email with Sitecore MainUtil class

Send Email with Sitecore MainUtil class

In my previous blog we were sending email by using SMTP client and reading Parameter from WFFFM actions parameter field. Sitecore also provides a MailUtil class for sending the email by calling SendMail function.

SendMail required System.Net.Mail.MailMessage type for parameter. Please use System.Net.Mail not System.Web.Mail and also we need to update sitecore.config file for SMTP settings.

Here is sample code for sending email using MainUtil Class.

public bool SendXPEmail(string from, List<string> tos, List<string> ccs, List<string> bccs, string subject, string body)

{

try

{

var emailMessage = new MailMessage();

emailMessage.From = from.IsNotNullAndNotEmpty() ? new MailAddress(@from) : new MailAddress(“noreply@sitecorexpblog.wordpress,com”);

foreach (var to in tos)

{

if (to.IsNotNullAndNotEmpty())

emailMessage.To.Add(to);

 

}

if (ccs.Any())

{

foreach (var cc in ccs)

{

if (cc.IsNotNullAndNotEmpty())

emailMessage.CC.Add(cc);

}

}

if (bccs.Any())

{

foreach (var bcc in bccs)

{

if (bcc.IsNotNullAndNotEmpty())

emailMessage.Bcc.Add(bcc);

}

}

emailMessage.Subject = subject;

emailMessage.Body = body;

emailMessage.IsBodyHtml = true;

MainUtil.SendMail(emailMessage);

return true;

}

catch (Exception ex)

{

Log.Error(“Something going wrong with Greeting card send email:”, ex);

return false;

}

}