Get item based on displayname in sitecore - sitecore

I need to get a specific item based on it's displayname, how do I do that?
For example I want to get this item /sitecore/content/mysite/about
But on the site is translated to multiple languages and could be something like www.site.com/om (in Sitecore it would be /sitecore/content/mysite/om)

There are a couple approaches you can take. The most efficent is to leverage the Content Search API, but the challenge is that Display Name is excluded from the index by default. A simple patch file can fix this:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<contentSearch>
<indexConfigurations>
<defaultLuceneIndexConfiguration>
<exclude>
<__display_name>
<patch:delete />
</__display_name>
</exclude>
</defaultLuceneIndexConfiguration>
</indexConfigurations>
</contentSearch>
</sitecore>
</configuration>
Then your code would be something like:
public Item GetItemByDisplayName(string displayName)
{
var searchIndex = ContentSearchManager.GetIndex("sitecore_master_index"); // sub your index name
using (var context = searchIndex.CreateSearchContext())
{
var searchResultItems =
context.GetQueryable<SearchResultItem>().Where(i => i["Display Name"].Equals(displayName)).FirstOrDefault();
return searchResultItems == null ? null : searchResultItems.GetItem();
}
}
This all is assuming you are on Sitecore 7. If you're on Sitecore 6, your option are limited and are probably not going to perform well if you content tree is large. Nonetheless, your function might look like:
public Item GetItemByDisplayName(string displayName)
{
var query = string.Format("fast:/sitecore/content//*[#__Display Name='{0}']", displayName);
var item = Sitecore.Context.Database.SelectSingleItem(query);
return item;
}
Please note that this will be horribly inefficent since under the covers this is basically walking the content tree.

Often, you wouldn't need to. LinkManager (responsible for generating all your item URLs) has an option to base the URLs on Display Name instead of Item.Name.
var d = LinkManager.GetDefaultUrlOptions();
d.UseDisplayName = true;
This can also be configured in configuration. Find and amend this section in your Web.config (or patch it via include files):
<linkManager defaultProvider="sitecore">
<providers>
<clear />
<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel"
addAspxExtension="false" alwaysIncludeServerUrl="false" encodeNames="true"
languageEmbedding="never" languageLocation="filePath" lowercaseUrls="true"
shortenUrls="true" useDisplayName="false" />
</providers>
</linkManager>
To truly do exactly what you ask is a quite involved process. If you point DotPeek to Sitecore.Pipelines.HttpRequest.ItemResolver, you can step through the ResolveUsingDisplayName() method. It essentially loops through child items, comparing the URL Part to the "__Display Name" field. You would have to cook up something similar.

Related

Switch between languages in content editor programmatically in sitecore

I want to switch between languages in content editor programmatically after saving item in sitecore
One way to achieve the desired result is to add a processor to the saveUI pipeline, that will reference ContentEditorDataContext and will change its language. To do so, we need to create a class with Process method like so:
public class LanguageChangeAfterSave
{
public void Process(Sitecore.Pipelines.Save.SaveArgs args)
{
var contentEditorDataContext = Sitecore.Context.ClientPage.FindControl("ContentEditorDataContext") as Sitecore.Web.UI.HtmlControls.DataContext;
contentEditorDataContext.Language = Language.Parse("en");
contentEditorDataContext.Refresh();
}
}
And in order to add this pipeline processor to the saveUI pipeline, we also create a .config file with the following content, and drop it to the webroot\App_Config\Include\ dirctory:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<processors>
<saveUI>
<processor type="YourNamespace.LanguageChangeAfterSave,YourAssembly" />
</saveUI>
</processors>
</sitecore>
</configuration>

Sitecore LinkManager url encoded

This seems trivial, yet I can't find an existing answer online...
I'm using Sitecore and I have configured it to use an item's display name to generate its url (using the "useDisplayName" setting).
Now, when I have an item with display name "Test, with commä"
I would expect Sitecore's LinkManager to provide me with a valid URL:
/nl-NL/ContentPage/Test%2C-with-comm%C3%A4
However, it gives me an URL with the invalid characters not encoded:
/nl-NL/ContentPage/Test,-with-commä
Now I know I can make exceptions for specific characters, but that's not the point. I'd like Sitecore to remove ANY illegal URL characters with their encoded counterparts.
Isn't there a setting or a simple way to achieve this?
Unfortunately Sitecore does not support encoding url parts in a way you want it.
And encodeNames="true" only tells Sitecore to use what is configured in encodeNameReplacements setting.
You have 2 options:
Contact with Sitecore Support and tell them about this bug.
Override LinkProvider class and encode urls:
public class CustomLinkProvider : Sitecore.Links.LinkProvider
{
public override string GetItemUrl(Item item, UrlOptions options)
{
var itemUrl = base.GetItemUrl(item, options);
// your code to encode the url
return itemUrl;
}
}
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<linkManager>
<providers>
<add name="sitecore">
<patch:attribute name="type">My.Assembly.Namespace.CustomLinkProvider,My.Assembly</patch:attribute>
</add>
</providers>
</linkManager>
</sitecore>
</configuration>

Can't Disable Display Name in URL

I have display name in URL disabled:
<linkManager defaultProvider="sitecore">
<providers>
<clear />
<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="false" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="never" languageLocation="filePath" lowercaseUrls="false" shortenUrls="true" useDisplayName="false" />
</providers>
</linkManager>
But I can still browse to the display name. I have no custom ItemResolver. I can't figure out why I can browse to these pages by display name.
It's LinkProvider which is responsible for url generation. It has nothing to do with browsing to the url.
For browsing the url you would need to write your own ItemResolver.
Default Sitecore ItemResolver class has a method which tries to resolve item based on its display name and there is no setting which would allow you to disable it out of the box.
It is because you are just setting the Link Provider to not use Display Names when generating the links.
Sitecores Link Provider and Item Resolver use different code. In the item resolver, if the item cannot be resolved by the direct path it calls this code:
Item obj2 = this.ResolveUsingDisplayName(args);
So it will also resolve by the display name.
To change that you would need to override the ItemResovler and remove that line of code.

Sitecore not taking language in url

Urls containing language information in the url ("filePath") opened normally in Sitecore 7.
For example, opening url "mysite.com/fr-ca" used to render an item with language fr-ca. Now, sitecore is displaying "item not found" page.
I have implemented a custom url provider. Is this causing issue?
I have changed "languageEmbedding" in hope that it works, but to no avail.
How can I fix this issue? As far as I remember this should work without issues as this functionality comes out of the box with sitecore.
The first thing to check is that your site has been published in the required language?
Publishing aside, it's difficult to know what the issue is here without seeing the code of your custom LinkProvider. If you were to use the standard Sitecore LinkProvider your settings should be similar to this (the key attributes to note here are languageEmbedding="always" and languageLocation="filePath"):
<linkManager defaultProvider="sitecore">
<providers>
<clear />
<add name="sitecore"
type="Sitecore.Links.LinkProvider, Sitecore.Kernel"
addAspxExtension="false"
alwaysIncludeServerUrl="false"
encodeNames="true"
languageEmbedding="always"
languageLocation="filePath"
shortenUrls="true"
useDisplayName="false" />
</providers>
</linkManager>

add target="_blank" to a General Link in Sitecore

I have general field in sitecore which can have internal or external link. I need to add target="_blank" for only external link.
I tried setting target window as new browser on click of "Insert External Link" in Sitecore, but no use.
It's ok if I add target=_blank from code also.
Code :
UrlOptions urlOptions = new UrlOptions();
urlOptions.LanguageEmbedding = LanguageEmbedding.Never;
Title = FieldRenderer.Render(item, "Title");
Summary = FieldRenderer.Render(item, "Short Description");
Details = FieldRenderer.Render(item, "Details");
Sitecore.Data.Fields.LinkField lf = item.Fields["TitleUrl"];
if (lf.Url != "")
{
ItemUrl = EFI.Library.SitecoreDataUtil.GetUrlForLinkField(lf, item, urlOptions);
}
else
{
ItemUrl = LinkManager.GetItemUrl(item);
}
Have you tried the following?
Render a General Link in Sitecore with target="_blank"
If you do not want to embed language you can set it for all links in web.config by setting languageEmbedding="never":
<linkManager defaultProvider="sitecore">
<providers>
<clear />
<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="never" languageLocation="filePath" shortenUrls="true" useDisplayName="false" />
</providers>
</linkManager>
Or you could open the link in a new window using jQuery on all anchor tags that start with http:
$(document).ready(function(){
$('a[href^=http]').click(function(){
window.open(this.href);
return false;
});
});
I agree with jammykam, if you never want to embed the language it's best to set it in the web.config. That way it'll be consistent across the board (and there's no chance you'll forget).
You can check in code whether your link is internal or external by using lf.IsInternal.
I think you could probably do something similar to this:
UrlOptions urlOptions = new UrlOptions();
urlOptions.LanguageEmbedding = LanguageEmbedding.Never;
Title = FieldRenderer.Render(item, "Title");
Summary = FieldRenderer.Render(item, "Short Description");
Details = FieldRenderer.Render(item, "Details");
Sitecore.Data.Fields.LinkField lf = item.Fields["TitleUrl"];
if (!lf.IsInternal)
{
lf.Target = "_blank";
}
ItemUrl = FieldRenderer.Render(item, "TitleUrl");
Interestingly, I don't see mention of the <sc:link /> control:
<sc:link runat="server" field="TitleUrl" />
And... that's it. Target for link selected in CMS will apply - of course that depends on your content authors selecting correct target, but gives enough flexibility for "exceptions to the rule". Anyway, just throwing another option out there. Good luck.