Pages

Tuesday, May 12, 2015

Sitecore List Fields - Item Not Found in Selection

I recently wrote an extension library for Sitecore to simplify setting values for fields.
Because of the way the specific field classes are created in Sitecore, setting values specific to the type of field can be tricky. For text-based fields, like Single-Line Text, Multi-Line Text, Rich Text, and a few others, you can actually set the value directly on a generic Field object with relative ease. For more complex types like lists, links, and images, though you can set the value directly on a generic Field object, setting the more specific options for the value needs more care.

So, I wrote an extension library to look at the Field type and set the value using the best method for that type. It worked great as far as I could tell, until I looked a little deeper during my "QA phase". And wouldn't you know it, it turns out there is a funky behavior with the list fields.

The Problem

Those sure look the same


I was using my library to set some fields and I noticed a strange behavior on my Checklist Field. Next to my selected values was the message "[Not in the selection List]." I have seen this before where there legitimately was no matching item in my list, but this value is being populated based on the Data Source for the field so the value is exactly the same. I even verified the GUIDs of the Items in the list and the values being set, and they were identical.

To eliminate any confusion and question of something in my library causing a unique problem, I selected the actual values in the list and wrote a quick code snippet to print them out to the page. At the same time, I set the value on the Field itself using a pipe-delimited string of GUIDs, directly copied from the items listed, just as the value shows. For further comparison, and validation, I output the value after I set it.

[pre class="brush:csharp" title="My snippet"]
var testItem = Sitecore.Context.Database.GetItem("{E0998AA4-B9FF-4D0D-BAE7-DC383E0777A1}");
var testField = testItem.Fields["Service Locations"];
Response.Write(testField.Value);
Response.Write("<br />");
string values = "{b4450adf-b0b6-4722-ab57-fc204ccfced2}|{0c985b30-95e9-42ea-9862-a05a3f0d2cd6}";
using (new EditContext(testItem)) {
    testField.Value = values;
}
Response.Write(testField.Value);
Response.Write("<br />");
[/pre]
And here is the resulting output:





The first GUID on the first line matches the second GUID on the second line. The second line matches exactly what I set it to, and it's the exact same format the previous value was. For all immediate purposes, they are the same items. It also makes sense because the Checklist Field in Content Editor shows the Items as values; it just shows "[Not in the selection List]" after them.

The Solution

No joke, I have been staring at this for over an hour, testing different methods of setting the value. I even changed my code to set the value to the value.
[pre class="brush:csharp" title="Another test"]
using (new EditContext(testItem)) {
    testField.Value = testField.Value;
}
[/pre]
And it worked fine, duh. However, looking at that screenshot above of the resulting output, you may have already figured it out. Though the GUIDs are the same, and the Items are obviously showing up in the list, the casing is different. Seriously.

When you set the value of the field, it's set to exactly what you put. So, if you set the value to a lowercase GUID, it's set at that. Likewise, if you set to an uppercase value, it stays at that. And you see that too, when you look at my resulting output screenshot. So, my hypothesis is that the casing is an issue. I tested my theory with the same value snippet, just above, setting the value to the existing value, but I added a ".ToLower()" to it. Sure enough, the value was identical to what it was, only lowercase, and the same message appeared.
[pre class="brush:csharp" title="Another test, ToLower"]
using (new EditContext(testItem)) {
    testField.Value = testField.Value.ToLower();
}
[/pre]
The only thing I can guess is that Sitecore does a "==" comparison, or a String.Compare of the value GUIDs to the Data Source GUIDs without specifying IgnoreCase, when the list field displays the items.

My final solution? So stupidly simple that I should have figured it out 1 1/2 hours ago. In my extension library all I needed was a ".ToUpper()" for whatever value is coming in and the problem is resolved.
[pre class="brush:csharp" title="Final Solution"]
var testItem = Sitecore.Context.Database.GetItem("{E0998AA4-B9FF-4D0D-BAE7-DC383E0777A1}");
var testField = testItem.Fields["Service Locations"];
Response.Write(testField.Value);
Response.Write("<br/>"); // something
string values = "{b4450adf-b0b6-4722-ab57-fc204ccfced2}|{0c985b30-95e9-42ea-9862-a05a3f0d2cd6}";
using (new EditContext(testItem)) {
    testField.Value = values.ToUpper();    // DoH! - solved
}
Response.Write(testField.Value);
Response.Write("<br/>");
[/pre]

Seriously? Damn you, Sitecore!


No comments:

Post a Comment