I'm working on a multilingual module right now and having problems with parsing a field to InternalLinkField. What happens is that I have an item in Chinese language, but when I get one of its field and convert it to InternalLinkField the converted item becomes English. Here's the sample code:
var field = (InternalLinkField)InnerItem.Fields["Test"];
So, the current item that I'm working on is the InnerItem, it is in Chinese version and when parsed the field object becomes English. So, as a workaround for now I used the context item to get the field with the language.
My workaround:
Item item = Sitecore.Context.Database.GetItem(field.TargetID, InnerItem.Language);
But, it is redundant and I want to know the right way to get the field object with the correct language version.
InternalLinkField is a system type used by Sitecore core. Hence, it is not recommended to use it for your custom features development unless you plan to extend Sitecore considerably. If you want to implement a link field in your data template then the following two types will be suitable for your need:
LinkField if you want to cover both internal and external links, i.e. admins can either select a Sitecore item or specify an external URL; you can simply use GetFriendlyUrl() method to generate the correct link as
Sitecore.Data.Fields.LinkField yourLinkField = yourItem.Fields["Link"];
var yourUrl = yourLinkField.GetFriendlyUrl();
Droplink if you want to restrict only to selection of a Sitecore item, such field will store ID of the selected item as value.
Related
Inside my custom save action, I iterate through the form fields (the AdaptedControlResult objects). Any form field which is a DropList (from any source -- manually entered values, or an item lookup) is returning a string value of System.Collections.Generic.List`1[System.String]
Now, it's important to know, it's not returning an actual List. It's returning a literal string with that value.
So, this call:
fields.GetEntryByName("MyFieldName").Value
Is returning the string: System.Collections.Generic.List`1[System.String]. Not the value of the dropdown. A string saying that's it's a List<string>.
I have confirmed the HTML of the form is rendering correctly. I have manually checked the inbound HttpContext.Current.Request.Form values as well...
HttpContext.Current.Request.Form["BGWnjkQqrE6w6sr31IgzrQ.Sections[5].Fields[0].Value"]
That is the correctly-selected value of the drop down (a Sitecore ID).
So, the data is getting output to the form correctly, and the inbound Request.Form data is also correct. Somewhere, Sitecore is deciding not to populate the selected value into the AdaptedControlResult object.
What's additionally odd is that for DropList field types, the selected value does appear in the Parameters property (inexplicably). I would just detect this and use it, but it's not consistent -- for instance, for textbox field types, the word "multiline" appears there.
All other field types work fine -- I have several text entry fields, and some radio button lists. It's just DropList fields.
What is the trick to getting this?
This is a known bug in Sitecore when using the WFFM module in MVC. You can find more details in this Knowledge Base Article - Incorrect data is saved for list fields in WFFM MVC.
The fix is listed on the kb article and depends on the exact version of Sitecore you are using. Sorry to provided a link only answer but there are multiple steps reqiured for the fix and the download for the fix is attached in the article.
Throughout my project I often use the Sitecore General Link field for links (external or internal or media). One standard I have is that for all of my pages there is a field on every page called "NavigationTitle". It allows the CMS author to control the display of the text for the item whenever that item is linked to. Ideally I would like to be able to find some way of having the system use that field from the target item whenever that item is linked to. Here is an example.
Let's say that all of the pages in my site have the following basic fields
NavigationTitle (text)
Content (rich text)
And let's say I have a data template called Promo. And Promo has the following fields:
Title (text)
Content (text)
Image (image)
Link (general link)
The Link field on a Promo could link to an internal page or even an external page. Right now when I build the sublayout to display a Promo, if I use a <sc:Link> tag to output the Link field I believe that Sitecore will first use the Text of the Link field for the text. Otherwise I think it will use the Item Name for the text.
I would like to build it so that instead of using the Item Name of the target item, I would like to use a particular field value from the target item. And I would like to have this code run at a low enough level so that this would work in conjunction with something like Glass Mapper. So that when I use Glass Mapper to output the Link field (using something like the Editable method) that it would display the correct link text.
Does anyone know how I would do this? I'm guessing that I might have to create a custom General Link Field that inherits from the normal General Link Field and overrides something. Just a guess. Any help is appreciated.
Definitely doable, you're best bet will be to add your own pipeline step before the GetLinkFieldValue renderField step. The GetLinkFieldValue uses the LinkRenderer class which does the following cascade to determine what to put in as the link text.
Value set on RawParameters property of the arguments object (only if there's one value)
Text Parameter in the Parameters property of the arguments object
Description on the link field
Item Name
We can set the value of the text parameter.
Configuration
<renderField>
<processor type="MyLibrary.Pipelines.AddNavigationTitle, MyLibrary" patch:before="*[#type='Sitecore.Pipelines.RenderField.GetLinkFieldValue, Sitecore.Kernel']" />
</renderField>
Code
public class AddNavigationTitle
{
public void Process(Sitecore.Pipelines.RenderField.RenderFieldArgs args)
{
if (args.FieldTypeKey == "general link")
{
Sitecore.Data.Fields.LinkField linkField = args.Item.Fields[args.FieldName];
if (linkField != null && linkField.TargetItem != null)
{
var title = linkField.TargetItem["NavigationTitle"];
if (!string.IsNullOrWhiteSpace(title))
{
args.Parameters["text"] = title;
}
}
}
}
}
Any time you render a general link field this will run and add in the text from the NavigationTitle field. You also get the added benefit in that if the field isn't filled in it will still cascade down the priority list from above.
Your best option with Glass is to implement a custom data handler, you could do this by copying the Link Mapper:
https://github.com/mikeedwards83/Glass.Mapper/blob/master/Source/Glass.Mapper.Sc/DataMappers/SitecoreFieldLinkMapper.cs
Then update line 130:
https://github.com/mikeedwards83/Glass.Mapper/blob/master/Source/Glass.Mapper.Sc/DataMappers/SitecoreFieldLinkMapper.cs#L130
You will then need to register you new handler in the GlassMapperScCustom class that is part of your solution. You do this in the CastleConfig method, you can see how registrations are done here:
https://github.com/mikeedwards83/Glass.Mapper/blob/master/Source/Glass.Mapper.Sc.CastleWindsor/SitecoreInstaller.cs#L189
We are using Sitecore 7.2 with multi-site implementation. The actual data is shared between multisite, hence it's been stored in common Global Item folder.
We are facing a problem generating aunique ID on URL. I had a good search but could not find any solution except to use Sitecore Item ID.
This is what we want:
domain/players/player_id
e.g. domain/players/1234
where 1234 is uniquely generated ID.
Could someone please suggest if this is possible?
Every page that is managed in Sitecore is a Sitecore Item. As such, you should be able to just navigate to the name of the player item. If you were trying to say in your post that player items are stored in globals and not as pages, then you are left with the following options:
Query String: domain/players/player?playerId={ID}
If this is the route that you choose to take then I would suggest using the player item's Sitecore ID for the value of the query string parameter.
If you have other IDs then put the specified ID there, however it would be easiest with Sitecore IDs
What you would then do is get the item with the ID specified in the query string parameter (or get the item with the player ID specified in the query string parameter, depending on which route you take) and display the data for that player on the page
Sitecore.Context.Database.GetItem(Request.QueryString["playerId"])
playerItems.FirstOrDefault(playerItem => playerItem["Player ID"] == Request.QueryString["playerId"])
Note that this assumes that the Player ID is a field, not the Sitecore ID
If it is the Sitecore ID then change the lambda to use playerItem.ID == new ID(Request.QueryString["playerId"]
Regardless of which one you use, I suggest adding null checks to the QueryString getter
Sublayout Parameters
If you use this method, the query string will not change and people will not be able to get to the page from the direct URL
The process is the same as for query strings, except that you are using Sublayout parameters instead
Note that you must set these in a parent sublayout or in Sitecore (which means that you have a separate page for each player - i.e. this would be a bad solution)
Virtual Items
This is really what I think you are looking for
This can be a lot of work if you do it from scratch, or you can use the Wildcard Module
If you do it from scratch, you will need a custom pipeline and/or processor for handling the requests
Good suggestions from Zachary. I will add a couple more:
1) IIS Rewrite Module. If what you are really after is having external URLs look like /domain/players/1234, you could easily accomplish this by forwarding these requests to something like Zachary's option #1. The client sees /domain/players/1234, but it's really handled by a single Sitecore item at /domain/player/player.aspx?playerid=1234. Client doesn't have to know that.
2) Custom ItemResolver pipeline handler. Custom Pipelines may be a bit intimidating at first, but they are actually pretty easy to implement and highly useful. Would be pretty straightforward to add a new one which checked for "players/1234" and set the ContextItem to your player handling page and drop the ID into a session variable or some context variable.
Before digging into my explanation i will summarize my question:
How do I provide the user (editor) with a user-friendly possibility to select a datasource item for sublayouts that are preset on the standard values?
My situation is as follows:
I have a page template, with pre-defined layout on the standard values.
Let's say the layout consists of:
one placeholder "wrapper"
one sublayout "content"
This sublayout is pre-defined on my page template, but can also be placed in the placeholder using the Page Editor.
It needs to have a datasource item that defines a Title and Body value.
Now, if a user adds this sublayout to the placeholder using the Page Editor, he will get a nice interface to select or create the datasource item (see screenshot).
However, if the sublayout was pre-defined on the standard values, it will be added without datasource (I can't pre-set the data source in the standard values because it's still unknown by then).
At that point there seems to be no way to get to that nice interface for selecting or creating a datasource item.
Ideally I want to be able to add a field to my template that can hold a datasource item which the user can select/create using the nice interface. I looked at the datasource field type, which could be an alternative, but it's still not exactly what I want.
Bare in mind that the content sublayout is just an example.
I understand that in that specific case I could solve it by always adding a title/body field to the template which hold the values if there is no datasource, but for my real world problem that won't suffice.
I don't have a whole lot of experience with the Page Editor (with the new way of working with it) so I would like to get some advice on this subject.
According to what you said here:
Ideally I want to be able to add a field to my template that can hold a datasource item which the user can select/create using the nice interface. I looked at the datasource field type, which could be an alternative, but it's still not exactly what I want.
It seems you want an intuitive data source selector interface in the CMS shell similar to the Page Editor-based UI.
Quick answer: Simply put, there's nothing that does this for you in Sitecore.
Longer answer: There are still some options for you, e.g.
Define a global "dummy" data source and set that to be the data source set in in Presentation > Layout Details of the template's standard values. So every time you create a new page, it will always point to that dummy value to show something.
From here you can do a few things:
If the user must use the shell UI and not Page Editor, they can simply create another data source item for the specific page and update that page to point to it using the existing native interface in Layout Details.
Another option is to write an event handler, say for item:created or similar that when you create an item, auto-create a corresponding data source item for this specific page (whether this auto-created item be a sub-items or global item...) then programmatically set this to be the data source. A similar concept is shown in this video by Nick Wesselman: http://www.techphoria414.com/Blog/2012/May/Sitecore_Page_Editor_Unleashed
In a Sitecore Treelist or Multilist, items available for selection and items that have been selected are displayed using their Display Name. However, the language version that the Display Name is pulled from is the current Client Language, not the currently selected language of the item being edited.
An example illustrates the problem a little better...
We are importing a large amount of content into Sitecore in en-GB. We are not creating en versions of this content. Authors are logging in with a default content language of en-GB. However, Sitecore Client Language is only available in base en. The actual name of these items is not very useful (it's an external system ID), so we want the authors to see the en-GB Display Name in Treelist, Multilist, etc. However since their Client Language is en, they do not.
I see two potential solutions:
Somehow modify or trick the controls into using the currently selected language of the content item when rendering list items. (Preferable)
Somehow duplicate the en Client Language so we can set the user's Client Language to en-GB.
Any ideas on how to execute either solution, or alternative approaches to solving the problem would be appreciated.
Does this get you started?
What if you implement the Language Fallback Item Provider and set en to be the fallback language for en-GB? That will then show the en display name in the case where it doesn't exist for en-GB.