Azure Search Sitecore

Azure Search – Sitecore

With the advancing technology, you can’t continue using the same methods and tools for your business every time. It is essential to make use of the new technologies and tools so as to meet the changing and growing needs and demands of your business. One such new technology that has come up is Sitecore, which acts as an extensible platform to capture, store, manage and distribute your content in a secure and reliable manner. It is getting massively popular amongst businesses because of the flexibility, security and scalability that it provides, which helps in enhancing user experience and allows businesses to effectively maintain their online brand presence and visibility. Sitecore CMS enables businesses to have full control of their website.

Sitecore Azure

Although Sitecore itself has had a lot of success as an ‘on-premises’ software solution and content management system that facilitates on-premises deployments, deploying #Sitecore on #Azure makes it even more better as ‘Sitecore Azure’.

azure-search-1

There are two very important terms in Sitecore Azure:

1. Azure Search – Sitecore

2. Redis Cache – Sitecore

Here in this post, we are going to know in depth about Azure Search feature of Sitecore.

Sitecore Azure Search

Sitecore Azure Search provider integrates the Sitecore Search engine with Microsoft Azure’s Search Service, which is a part of Microsoft Azure computing platform.

Features of Azure Search

Which features of Azure Search make it a good deal to deploy Sitecore on Azure? And how does Azure Search – Sitecore help businesses? Some of the beneficial features of Azure Search services of Sitecore are as follows:

1. Azure Search offers extreme simplicity, scalability and stability that can be utilized to boost the user experience and performance on any business website.

2. You get support for all Sitecore search-driven UIs, including user-typed queries, and faceted searches.

3. Sitecore Azure Search also provides support for the majority of LINQ expressions, to enable rapid development of search-powered applications.

4. You get local/native support for fundamental data types such as numbers and dates in faceting, and range queries.

5. With Sitecore Azure Search, you get flexible configuration and precise control over the schema of the indexes.

6. It also offers support for running Sitecore in geo-replicated scenarios.

It is important to note here that Sitecore Azure Search is the default provider for Sitecore instances that are deployed using Sitecore Azure SDK.  Sitecore Azure Search supports on-premises and IaaS (Infrastructure as a Service) deployments. However, you shall have to configure Azure Search service with your Sitecore instance by creating a Search service, formatting the connection strings, setting up configuration files, rebuilding the indexes, mapping the Azure field types and fields and support for Azure Search.

How is Sitecore Azure Search different from Lucene and Solr search providers?

While using Sitecore Azure Search you must be aware that Sitecore Azure Search is different from the Lucene and Solr search providers. This is important to know, especially when you plan to switch between search providers.

azure-search-2.jpg

Azure Search Service is a fully managed, cloud-based service that allows developers to build rich search applications using REST APIs. This includes full-text search scoped over your content, along with advanced search behaviours similar to the ones found in commercial web search engines, like type-ahead, suggested queries based on near matches, and faceted navigation.

You can use Solr if you have a scaled environment with two or more delivering servers or two or more content authoring servers or in case you have separate servers for email, processing, reporting and publishing. The indexes are available to all servers in the environment.

On the other hand Lucene is a file-based indexing system, which means that if an index is not located on the server that the request is coming from you have to ensure that indexes across all servers remain in sync.

In the coming post, I shall also be talking about Redis Cache, what it is about and what it has to do with Sitecore.

301 Redirect for Media Item

We recently had a requirement about 301 redirect for media item like pdf files. Sitecore Shared Source 301 Redirect module was used for 301 redirect, but it does not support 301 redirect for media item requested url, because sitecore MediaRequestHandler redirect to ItemNotFoundUrl, if requested URL does not exist in sitecore.

CustomMediaRequestHandler allows you to extend the default MediaRequestHandler, so you can easily check if the requested media Url from redirect url module, does not exist in sitecore media library, then get value of “Redirect to Item” or “Redirect to Url”, and redirect web request on these value.

Custom DoRedirect function process if request media is not in sitecore.

Because this configuration is not within the /configuration/sitecore element, this requires one or two updates to the /web.config file itself. Under the /configuration/system.webServer/handlers element:

<!–<add verb=”*” path=”sitecore_media.ashx” type=”Sitecore.Resources.Media.MediaRequestHandler, Sitecore.Kernel” name=”Sitecore.MediaRequestHandler”/>–>
<add verb=”*” path=”sitecore_media.ashx” type=”Project.Framework.CustomMediaRequestHandler, Project.Framework” name=”Sitecore.MediaRequestHandler”/>

public class CustomMediaRequestHandler : MediaRequestHandler
{
protected override bool DoProcessRequest(HttpContext context)
{
Assert.ArgumentNotNull((object)context, “context”);
MediaRequest request = MediaManager.ParseMediaRequest(context.Request);
if (request == null)
return false;
Media media = MediaManager.GetMedia(request.MediaUri);
if (media != null)
return this.DoProcessRequest(context, request, media);
using (new SecurityDisabler())
media = MediaManager.GetMedia(request.MediaUri);
string str;
if (media == null)
{
str = DoRedirect(context) ? string.Empty : Settings.ItemNotFoundUrl;
}
else
{
Assert.IsNotNull((object)Context.Site, “site”);
str = Context.Site.LoginPage != string.Empty ? Context.Site.LoginPage : Settings.NoAccessUrl;
}
if (!string.IsNullOrEmpty(str))
{
if (Settings.RequestErrors.UseServerSideRedirect)
HttpContext.Current.Server.Transfer(str);
else
HttpContext.Current.Response.Redirect(str);
}
return true;
}

private IEnumerable<Item> GetRedirects(Database db, string templateName, string versionedTemplateName, string queryType)
{
IEnumerable<Item> enumerable = (IEnumerable<Item>)null;

string setting = Sitecore.Configuration.Settings.GetSetting(SharedSource.RedirectModule.Constants.Settings.RedirectRootNode);

switch (queryType)
{
case “fast”:
IEnumerable<Item> first = (IEnumerable<Item>)db.SelectItems(string.Format(“fast:{0}//*[@@templatename='{1}']“, (object)setting, (object)templateName));
IEnumerable<Item> source = (IEnumerable<Item>)db.SelectItems(string.Format(“fast:{0}//*[@@templatename='{1}']“, (object)setting, (object)versionedTemplateName));
enumerable = Enumerable.Any<Item>(source, (Func<Item, bool>)(i => i.Versions.Count > 0)) ? Enumerable.Union<Item>(first, Enumerable.Where<Item>(source, (Func<Item, bool>)(i => i.Versions.Count > 0))) : first;
break;
case “query”:
enumerable = (IEnumerable<Item>)db.SelectItems(string.Format(“{0}//*[@@templatename='{1}' or @@templatename='{2}']“, (object)setting, (object)templateName, (object)versionedTemplateName));
break;
default:
Item obj = db.SelectSingleItem(setting);
if (obj != null)
{
enumerable = Enumerable.Where<Item>((IEnumerable<Item>)obj.Axes.GetDescendants(), (Func<Item, bool>)(i => i.TemplateName == templateName || i.TemplateName == versionedTemplateName));
break;
}
else
break;
}
return enumerable ?? (IEnumerable<Item>)new Item[0];
}

protected bool DoRedirect(HttpContext context)
{
string input = HttpContext.Current.Request.Url.ToString();
string absolutePath = HttpContext.Current.Request.Url.AbsolutePath;

Database database = Context.Database;

//bool isRedirectUrl = false;
Item redirectUrlItem = null;
foreach (Item redirectItem in GetRedirects(database, SharedSource.RedirectModule.Constants.Templates.RedirectUrl, SharedSource.RedirectModule.Constants.Templates.VersionedRedirectUrl, Sitecore.Configuration.Settings.GetSetting(SharedSource.RedirectModule.Constants.Settings.QueryExactMatch)))
{
if (input.Equals(redirectItem[SharedSource.RedirectModule.Constants.Fields.RequestedUrl], StringComparison.OrdinalIgnoreCase) ||
absolutePath.Equals(redirectItem[SharedSource.RedirectModule.Constants.Fields.RequestedUrl],
StringComparison.OrdinalIgnoreCase))
{
//isRedirectUrl = true;
redirectUrlItem = redirectItem;
break;
}
}

if (redirectUrlItem != null)
{
context.Response.StatusCode = 301;
if (!string.IsNullOrEmpty(redirectUrlItem[SharedSource.RedirectModule.Constants.Fields.RedirectToItem]))
{

var sitecoreItem = redirectUrlItem[SharedSource.RedirectModule.Constants.Fields.RedirectToItem];
var item = Sitecore.Context.Database.GetItem(sitecoreItem);
//MediaItem mediaItem = item;

var isMediaItem = MediaManager.HasMediaContent(item);

if (isMediaItem)
{
var mediaItemUrl = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) + MediaManager.GetMediaUrl(item);
context.Response.AddHeader(“Location”, mediaItemUrl);
return true;
}

var redirecturl = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) + LinkManager.GetItemUrl(item);
context.Response.AddHeader(“Location”, redirecturl);
return true;
}
if (!string.IsNullOrEmpty(redirectUrlItem[SharedSource.RedirectModule.Constants.Fields.RedirectToUrl]))
{
var redirecturl = redirectUrlItem[SharedSource.RedirectModule.Constants.Fields.RedirectToUrl];

context.Response.AddHeader(“Location”, redirecturl);
return true;
}

}

return false;
}
}

This way we can 301 redirect for sitecore media item .