Build validation rules for item DisplayName property - sitecore

I'm working on a multi-language solution in Sitecore and want to use the DisplayName property of an item to represent the URL to allow for language-specific URLs.
I've set the useDisplayName web.config property to true as shown below
<linkManager defaultProvider="sitecore">
<providers>
<clear />
<add name="sitecore"
alwaysIncludeServerUrl="false"
encodeNames="true"
type="Sitecore.Links.LinkProvider, Sitecore.Kernel"
addAspxExtension="false"
shortenUrls="true"
languageEmbedding="asNeeded"
languageLocation="filePath"
useDisplayName="true" />
</providers>
</linkManager>
I've also been playing with the <encodeNameReplacements> section which can replace %20 with a hyphen in the URL to give nice clean URLs - this is done with the following for those who are interested:
<replace mode="on" find=" " replaceWith="-" />
All very good, except that Sitecore breaks if a user enters a hyphen within a DisplayName with the above setting turned on.... If I turn the above setting off, then I have to ensure that users enter nice hyphen separated values for the DisplayName otherwise we start seeing nasty %20s again in the URL...
So, is there a way to validate the DisplayName property to either disallow or allow hyphens being used?
Or, even better, is there a way to hook into whatever code is executed when the encodeNameReplacements thing happens? This would be ideal, as I could allow users to enter whatever they like for DisplayName, then just sanitise this value on the fly.

There is a solution for this, but it will require some coding and it's quite complex.
I have used this kind of solution in many projects before and it's the only way of solving this, that i'm aware of.
You don't want to really replace spaces with hyphens when saving the item, because it's not user friendly.
My solution works at runtime.
First get rid of the <replace> rule you added.
Then create your own LinkProvider (inherit from Sitecore's default provider).
Inside the LinkProvider create a method to "normalize" the item's displayname (e.g. replace spaces for hyphens), let's call this method NormalizeDisplayName(). Make it public and static cause you will need it later.
So now you have managed to let Sitecore replace all spaces with hyphens in links. The rest you can still configure using the default provider options (addAspxExtension="false" useDisplayName="true", etc)
Next up is the ItemResolver: Sitecore's default ItemResolver is not going to recognize the item path anymore so you are going to add your own ItemResolver to fix this.
Create a class that inherits from Sitecore.Pipelines.HttpRequest.HttpRequestProcessor and configure it to be used in the <httpRequestBegin> pipeline after the default ItemResolver.
Now, when the itemresolver is processed you will first split up the requested itempath (let's assume that "/category-name/subitem-name" was requested).
Starting from the siteroot (which can be pulled from Sitecore.Context.Site), loop through all children while normalizing their item names using your NormalizeDisplayName() method you created earlier, until you find one that matches the part of your item path.
So in this case, loop through the children of your Home item until you find one that matches normalized displayname "category-name". Then do the same thing for the children of that item until you find the item with normalized displayname "subitem-name".
This way you can resolve the requested item and it will also work if the original displayname already contained hyphens!
I'm sorry that I can't give you complete code examples as it's quite complex and is not limited to just the above things. You also need to think about redirecting if the URL is not properly formatted and make exceptions for master/core database to prevent Sitecore from breaking.
Hope this helps you!

If you see the source in .net reflector (Sitecore.Shell.Framework.Commands.SetDisplayName) there are no pipelines that runs.
You could make a Saving event, making the display name, as you want replacing hypen with a space
public void OnItemSaving(object sender, EventArgs args)
{
Item item = Event.ExtractParameter(args, 0) as Item;
item.Appearance.DisplayName = item.Appearance.DisplayName.Replace("-", " ");
}
Just a quick example of the event

Related

Regex in capybara have_xpath

I have a text changing decoration when it is clicked. In my tests before clicking I want to check whether it's already clicked or not. It changes color, text decoration and href which I want to check through.
As href contains session specific information, so I want to use regex.
if page.have_xpath("//a[contains(#href,\"%20Administrators?\")]")
This passes even the page has already been updated and Administrators text has changed to something else.
How should I correct the syntax to accept all href containing "%20Administrators?" text. I want add it to if clause as if the page has the link with text Administrators in it.
Before clicking: href="/sometext/%20Administrators?redirect=sometext"
After clicking : href="/sometext/%20Standard?redirect=sometext"
The primary issue you're having here is using have_xpath rather than has_xpath?. have_xpath returns an RSpec matcher, and as such when used with if will always evaluate as true (since it returns an object and hasn't yet actually evaluated any XPath passed in). has_xpath? returns a boolean result of true or false.
if page.has_xpath?('.//a[contains(#href,"%20Administrators?")]')
The second issue is that your question asks about regex, but XPath 1.0 (which browsers support) doesn't have regex support and your XPath isn't using regex at all (just a contains expression). If you actually want to use regex for testing the href (and have better reading code) you should be using the has_link? boolean method - along the lines of
if page.has_link?(href: /Administrators/)
has_link? can also verify the visible text of the link too if wanted
if page.has_link?('Visible text of the link', href: /Administrators/)
Finally, when using XPath with Capybara, 99% of the time you should start your XPath with .// instead of just // - see https://github.com/teamcapybara/capybara#beware-the-xpath--trap - and is one reason why it's usually cleaner to use CSS and/or the more specific methods provided by Capybara rather than the xxx_xpath methods.
One other thing to note is that all of the methods mentioned have waiting behavior by default, so they will wait up to Capybara.default_max_wait_time seconds for the page to have a matching link. If you know the page is stable and just want to immediately know whether or not a matching link exists you might want to pass wait: false as an option
if page.has_link?(href: /Administrators/, wait: false)

Making sure custom tag does not have subtags

I am building custom tag to wrap around glyphicons.
<b:icon binding="i" />
Part of the Glyphicon spec includes:
Only for use on empty elements
Icon classes should only be used on elements that contain no text
content and have no child elements.
I want to make sure no one does something like
<b:icon binding="i">
<cfset myVariable++>
</b:icon>
Is there a way to make sure a custom tag does not have any inner tags?
Well you have two options that I can see.
First, throw an exception if thisTag.executionMode is anything other than "start". Or one could likewise throw an exception if thisTag.hasEndTag is true. However this will restrict tag usage to:
<b:icon binding="i">
And not:
<b:icon binding="i" />
Because /> is shorthand for an end-tag. This is less than ideal, and you perhaps won't accept that as an approach.
Secondly you can check if there's any generatedContent but this is a big haphazard because it's entirely possible to have something between starting and closing tags, but is careful to not generate content:
<b:icon binding="i"><cfset foo="bar"></b:icon>
(note: even the new lines and indentation would count as generatedContent if there were any).
Bottom line: whilst JSP custom tags allow for control of this sort of thing, I cannot see how it can be controlled by the CFML implementation. The closest you can get is to prohibit closing tags entirely.

What does add key value means in web.config file

HI all i am trying to figure out the values and their meanings in web.config files, there are two lines which are not making sense to me if you can elaborate on this please.
<add key="Imp.Import.shops.FileLocation" value="C:\_imp\" />
<add key="Imp.Import.shops.ArchiveLocation" value="C:\_imp\_archive\" />
It just allows for many entries for a section, the key must be unique. It's typically used when there is code written to look for that exact entry, for example the appSettings section of the web/app .config files are for general use. For those values to be loaded and used you must add code to look for a specific key so there is an implied contract between adding an item in the appSettings and adding code to actually use it.
To read the setting value:
Add a reference to System.Configuration.ConfigurationManager
Code:
var archiveLocation = ConfigurationManager.AppSettings["Imp.Import.shops.ArchiveLocation"];
If you didn't write the system then you can safely assume there is code written that needs to read these settings, the key identifies the setting by name.

Sitecore ECM 2.1 - branches, sublayouts and dynamic datasources

It's my first time implementing Sitecore ECM feature. I've cut up some html templates into layouts and sublayouts, created the datasources I needed, and made a branch template with the $name item set to be of template "AB Testable message".
Following Frank Rooijen's blog post: http://www.newguid.net/sitecore/2013/building-custom-newsletter-templates-for-sitecores-ecm-2-x/ I've set the body field in the $name to go to my message root child, set all the sublayout datasources to the relevant child items of the message root.
Andit all works fine!
What I really want to know is how the sublayout's datasource paths are derived to their new location after being instantiated from the create/insert action from the ECM Speak page.
I've been using reflector to try and get some insight, but I don't think I'm looking in the right places.
The ECM package adds a new config file at /App_Config/Includes/Sitecore.EmailCampaign.config. Within that file you can see some new event handlers are added, most notably:
<event name="item:added">
<handler type="Sitecore.Modules.EmailCampaign.Core.ItemEventHandler, Sitecore.EmailCampaign" method="OnItemAdded" />
</event>
<event name="item:copied">
<handler type="Sitecore.Modules.EmailCampaign.Core.ItemEventHandler, Sitecore.EmailCampaign" method="OnMessageCopied" />
</event>
If you decompile Sitecore.EmailCampaign.dll and look at the corresponding Class and follow through the code you will see call to MessageRelationsCorrector.CorrectItemRelations() which handles all the work to replace the IDs of the DataSources of new created and copied messages.
jammykam is spot on.
The one thing that I'd add though (after banging my head for a while) is that even though the processing first does a check on template descends from AB Testable Message or the other email types, the actual correction of item relations only happens if the email template is exactly one of the built-in templates like AB Testable Message. Don't try and have you own template that derives. Sigh.

Umbraco error in Document Types

A long time ago I first setup a website in Umbraco. This seemed to be working fine.
I have now come back to it about a year later, and was initially getting the following error when selecting a Document Type (any document type in the Settings tab):
A bit weird, because earlier I didn't have this issue, but fine. I do what it says, and add <identity impersonate="true"/> to the <system.web> node in web.config.
While it does fix the initial issue, I now have the following on all document types:
When trying to create a new Document Type, I get the same kind of error, but then the ReturnUrl part is ReturnUrl=/umbraco/create.aspx?nodeId=init&nodeType=inittemplates&nodeName=Templates&rnd=20.2&rndo=21.2&nodeId=init&nodeType=inittemplates&nodeName=Templates&rnd=20.2&rndo=21.2' - but only if I tick the box 'Create template for this item'. The same happens when I try and create a Template.
After Googleing I came up with this: our.umbraco post with similar issue. One (unconfirmed) solution is that there's an illegal name in a document type/ template - but I haven't changed anything, and might be fixed by going into the database.
I did check the /masterpages folder, the only 'strange' characters in there are - and _.
In my Document Types I have on named 'Textpage (Two col)' and another named 'News & Events list'. I'm a bit hesitant to just delete them, since I don't have enough Umbraco knoledge to be sure this will fix my issue...
Is there any known solution for this, or will I also have to go into the database (and if so, whereabouts?)
I'm running Umbraco 4.7.2, assembly version 1.0.4500.21031.
I've hosted this site with GoDaddy.com - I don't know if that would be relevant.
[Update 1]
As per Tom Maton's comment:
The requirepermissions should be set to false, and have been.
in Appsettings I've set this:
<add key="umbracoUseMediumTrust" value="true" />
And I've added Trusted_Connection=yes to the connectionstring.
the problem remains.
[Update 2]
Tried the solution amelvin provided, but no dice. Doctypes and templates still give the error. I'm getting more certain it's some security issues. Which folder would correspond to the Templates? Would that be the masterpages folder? If so, what kind of permissions does that one need?
It could be that you don't have full trust on your Go Daddy environment?
Check this post out http://our.umbraco.org/forum/getting-started/installing-umbraco/17856-Umbraco-on-GoDaddy-Shared-Hosting
Could help resolve your issue.
The error could be a knock on from permissions errors as yet unsolved.
But the error is thrown if the content page does not have a template assigned or if Umbraco thinks it doesn't have a template. If absolutely nothing has changed to the site then it could be that the umbraco.config file has somehow got corrupted (it will contain all the doctype/template cross reference info). This can be fixed by right clicking on the top 'content' node and choose 'republish entire website'.
Secondly navigate to the settings | document types (if you can now) and check the templates dropdown on the first tab of the appropriate document type. If its set to 'please select' then this error will get thrown when any page tries to render without a valid template assigned. If a default template is assigned - then go to that template and re-publish it - Umbraco may have lost it.
If this does not work then check if the template is assigned properly. Go to the same place in the content tree as the problem page and try to add a node with the desired doctype. If no choices are offered then it could be that the parent tab no longer allows the correct doctypes as children nodes, so go back to the doctypes and check the allowed children (second tab) of the parent node.
If none of this works without odd errors being thrown then its a mystery!
Here are a list of Permissions required for Umbraco http://our.umbraco.org/wiki/reference/files-and-folders/permissions
Or you could use one of the steps below to check all the folder permissions.
http://our.umbraco.org/wiki/reference/files-and-folders/permissions/perform-permissions-check
Or install this package. http://our.umbraco.org/projects/backoffice-extensions/ugolive this will allow you to check the permissions are correctly setup.