Using a SelectionFactory with ConentReference property issue

Vote:
 

I am attempting to use a selection factory to make choosing a specific kind of content type simpler. I am using a variation of this type of selection factory to list my content in a dropdown:
https://github.com/alfnilsson/episerverutils/blob/master/SelectContent/ContentSelectionFactory.cs

The problem is the property I am using the factory on will not serialize the selected value into a ContentReference properly. I get an error "Unable to cast object of type 'System.String' to type 'EPiServer.Core.ContentReference'" when saving the item. It works fine if I change the property to a string though, but it forces me to parse it into a ContentReference manually if I want to use it in code. Here is my property definition:

[Display(
GroupName = Global.TabNames.Location,
Name = "Location",
Order = 20)]
[SelectOne(SelectionFactoryType = typeof(LocationSelectionFactory))]
public virtual ContentReference Location { get; set; }


My selection factory uses this code to create the select items:

foreach (var location in locations) {
list.Add(new SelectItem {Text = location.Name, Value = location.ContentLink.ToReferenceWithoutVersion()});
}


Is there a step somewhere I am missing that can help with the conversion so I don't have to revert to using a string field?

#203759
May 06, 2019 21:25
Vote:
 

Hi Jason,

In terms of your current code it looks good and should work.

By any chance when you first created the property was it a string? If that's the case and you assigned a value then you'll probably find it's still a string in the database (Episerver always errs of the side of caution when data can be lost).

Navigate to CMS > Admin > Content Type and select your page or block type. Select you Location property and you'll probably see the Type is still Long string (>255). You just need to change it to Content Item and Save.

#203761
Edited, May 06, 2019 23:39
Vote:
 

I was under the impression that selection factory properties (SelectOne, SelectMany) must be strings. I usually do this:

[SelectOne(SelectionFactoryType = typeof(LocationSelectionFactory))]
public virtual string LocationRaw { get; set; }

public ContentReference Location
{
    get
    {
        if (!string.IsNullOrEmpty(LocationRaw))
        {
            return ContentReference.Parse(LocationRaw);
        }

        return null;
    }
}

I also use .ToString() when setting the value of the select item in the selection factory, otherwise the selection of correct item does not work as expected.

#203782
May 07, 2019 11:20
Vote:
 

I tried having a second ContentReference property that was not originally a string and it also failed. It fails the moment you make a selection, the UI starts to freak out and error pop up above the editor area saying "service is offline". I gave up on it and made it a string. 

#203799
May 07, 2019 15:40
Vote:
 

Strange.

It isn't a requirement that it's a string. It could be an enum backed by an int, or in Alloy there is an almost exact example of what you are trying to achieve: a PageLink selection factory which is used on a PageLink property.

It'd definitely be cleaner if you could avoid parsing it in a getter. Did you verify the type of the property?

#203804
May 07, 2019 16:34
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.