Create custom multiple choice field for BasicProfile using A

Posted by Community Admin on 04-Aug-2018 12:09

Create custom multiple choice field for BasicProfile using API; how to pass ChoiceItems

All Replies

Posted by Community Admin on 10-Oct-2013 00:00

Hi,

I'm trying to add a number of custom fields to the sitefinity Basic Profile using the API (version 6.1).
As a starting point I used the samples provided here:
www.sitefinity.com/documentation/documentationarticles/developers-guide/sitefinity-essentials/modules/ecommerce/product-types/custom-fields/creating-custom-fields

Since these samples add customfields to ProductTypes I altered the code somewhat and up to this point I can succesfully add ShortText-, LongText-, Date-, Number- and YesNoFields.

The MultipleChoiceField however brings me two problems:
1. The ChoiceItems I pass to  wcfField.Definition are not persisted; when I edit the custom field under Basic Profile, the default Choices (Choice 1, Choice 2 and Choice 3) are displayed in the Choices editor.
2. I'd like to enable  Multiple Selection for this MultipleChoice field, so I choose Definition.RenderChoiceAs = RenderChoicesAs.CheckBoxes and Definition.AllowMultipleSelection = true. The control however is rendered as RadioButtons and is not Multiple Selectable.

Used procedure:

public static void CreateMultichoiceField(string fieldName, string fieldLabel)
    var wcfField = new WcfField()
        
            Name = fieldName,
            ContentType = typeof(string).FullName,
            FieldTypeKey = UserFriendlyDataType.MultipleChoice.ToString(),
            IsCustom = true,
             
            //Database mapping
            DatabaseMapping = new WcfDatabaseMapping()
                
                    ClrType = typeof(string).FullName,
                    ColumnName = fieldName.ToLower(),
                    Nullable = true,
                    DbType = "VARCHAR",            
                ,
 
            //Field definition
            Definition = new WcfFieldDefinition()
                
                    Title = fieldLabel,
                    FieldName = fieldName,
                    FieldType = typeof (ChoiceField).FullName,
                
        ;
 
    var choiceItems = new List<ChoiceItem>();
     
    var choiceItem = new ChoiceItem() Text = "Dutch", Value = "NL", Selected = false ;
    choiceItems.Add(choiceItem);
    choiceItem = new ChoiceItem() Text = "English", Value = "EN", Selected = false ;
    choiceItems.Add(choiceItem);
    choiceItem = new ChoiceItem() Text = "French", Value = "FR", Selected = false ;
    choiceItems.Add(choiceItem);
    choiceItem = new ChoiceItem() Text = "German", Value = "DE", Selected = false ;
    choiceItems.Add(choiceItem);
             
    var serializer = new JavaScriptSerializer();
    wcfField.Definition.Choices = serializer.Serialize(choiceItems);
     
    //wcfField.Definition.ChoiceDefinitions = ????????
    //wcfField.Definition.ChoiceItemsTitles = ???????;
    //wcfField.Definition.SelectedChoicesIndex = null;
    wcfField.Definition.RenderChoiceAs = RenderChoicesAs.CheckBoxes;
    wcfField.Definition.AllowMultipleSelection = true;
 
    CustomFieldsContext.Validate(wcfField, TypeResolutionService.ResolveType("System.String"));
 
    var typeContext = new CustomFieldsContext(TypeResolutionService.ResolveType("System.String").FullName);
    typeContext.SaveFieldDefinition(wcfField, TypeResolutionService.ResolveType("System.String").Name, null);
    typeContext.SaveChanges();
 
    using (var metadataManager = MetadataManager.GetManager())
    
        var metaType = metadataManager.GetMetaType("Telerik.Sitefinity.Security.Model", "SitefinityProfile");
        var metaField = metadataManager.CreateMetafield(fieldName);
         
        metaField.Title = fieldLabel;
         
        CustomFieldsContext.SetFieldDatabaseMappings(metaField, metaType, UserFriendlyDataType.MultipleChoice, wcfField, metadataManager);
 
        metaField.MetaAttributes.Add(new MetaFieldAttribute Name = "UserFriendlyDataType", Value = UserFriendlyDataType.MultipleChoice.ToString() );
        metaField.MetaAttributes.Add(new MetaFieldAttribute Name = "IsCommonProperty", Value = "true");
 
        metaType.Fields.Add(metaField);
 
        metadataManager.SaveChanges();
    
 
    SystemManager.RestartApplication(false);

How to get this code doing what it is supposed to do?
Do the properties ChoiceDefinitions en/or ChoiceItemsTitles need to be initialized, or ...??

Apart from the issue mentioned above I'm experiencing two other smaller issues, not only applicable to MultipleChoice fields, but to all custom fields.
- The field LabeI passed to wcfField.Definition.Title and metaFiled.Title, is not pesisted; it defaults to the control name after creation.
- After the code has finished creating the custom fields, the fields are visible under Basic Profile; they are  however NOT visible in the users profile UNTIL I first open and directly save it under Basic Profile.

Can anyone please shed some light on these issues?

Thanx!

Herman

Posted by Community Admin on 15-Oct-2013 00:00

Hi Herman,

First of all thanks for your patience. The investigation of the problem took a bit more time.

You are absolutely right about MultipleChoiceField problems. We have created a PITS issue and you can vote to increase its priority for fixing. Anyone who is interested could vote.

Currently there is a workaround in order to use a custom field with checkboxes wherever you prefer (the example is for Basic Profile). I'll give you the steps in the UI (they can be achieved with code).

  1. Register database mapping for the new type in order to store the data of the field.
    1. Go to Administration > Settings > Advanced > Metadata > DatabaseMappings > Create New.
    2. Fill Name: CustomMultipleChoices, CLR type: System.String[], Database length: 255, SQL specific type: NVARCHAR, Datatype: VARCHAR, Nullable: true. (You could change the values as you prefer).
    3. Save changes
  2. Register the new custom field and specify the control that will be used to display its values
    1. Go to Administration > Settings > Advanced > Custom Fields > FieldTypes > Create new.
    2. Fill Name: CustomMultipleChoices, Title: CustomMultipleChoices
    3. Save changes
    4. Go to Controls subsection > Create new
    5. Fill: FieldTypdOrPath: Telerik.Sitefinity.Web.UI.Fields.ChoiceField, Title: ChoiceField, DesignerType: Telerik.Sitefinity.Web.UI.Fields.Designers.MultipleChoiceFieldDesigner, ResourceClassId: ModuleEditorResources
    6. Save changes
  3. Add this field where you want to use it (e.g. the user's profile)
    1. Go to Administration > Users > Manage Profile Types > Basic profile > Custom Fields > Add a field
    2. Fill Type: CustomMultipleChoices, Name: NameOfTheFields (e.g. Responsibilities), Continue > Done.
  4. Register the new custom field where you want it to be used (e.g. in backend edit view of the users, and each other view. The example is for edit screen of the user.
    1. Go to Administration > Settings > Advanced > ContentView > Controls > ProfileType_SitefinityProfile > Views > ViewBackendEdit > Sections > CustomFieldsSection > Fields > Responsibilities (or the newly added field name)
    2. Change RenderChoicesAs: CheckBoxes (it is RadioButton by default and could be modified here). ReturnValuesAlwaysInArray: true
    3. Go to ChoicesConfig subelement and change/add/remove the elements you want to be available as choices for the field. (There you could specify resources if you prefer).
    4. Save Change

I hope now you should be able to use the field as you expect.

Kind Regards,
DimBo
Telerik
Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

Posted by Community Admin on 17-Oct-2013 00:00

Hey DimBo,

The solution you descibe so detailed (addressing issue #2) works like a charm!     
Thank you for this!

The Question now is how to implement this functionality in code, espacially now I have to deal with a UserFriendlyDataType (CustomMultipleChoice) that's not available in code. This is a bit of a problem since I reference UserFriendlyDataType.xxxx several times (see sample in original post).
Do I have to register it somewhere to have this custom typa available in code?

Next to this the question remains (issue #1) how to pass a list of ChoiceItem (List<ChoiceItem>) to the custom field when created through the API... after creation of the field the ChoiceItems seem to have dissappeared leaving me with onley the default choices (Choice 1, Choice 2 and Choice 3)  :o( 

Thanx!

Herman
 

Posted by Community Admin on 22-Oct-2013 00:00

Hello Herman,

For steps 1, 2 and 4 you can use the ConfigManager to update the configurations and that's all. But for step 3 (updating the SitefinityProfile) - you are right - you are not able to use UserFriendlyDataType and call SetFieldDatabaseMappings method. I hope in one of our next releases you will be able to use an overload with string instead of predefined enum. But you could do the job by yourself. You have to set metaField properties and that's it (ClrType, DBType, DBSqlType, DBLength, DBScale, Required, ColumnName, Index - some of them are optional).
And finally for the #1 question - it is done via configuration (as specified in step 4. - so you could modify it again with ConfigManager

ConfigManager mgr = ConfigManager.GetManager();
var contentViewConfig = mgr.GetSection<ContentViewConfig>();
//update content view controls you want
//contentViewConfig.ContentViewControls.
mgr.SaveSection(contentViewConfig);

I hope you will be able to go further now.

Have a nice day,
DimBo
Telerik
Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

Posted by Community Admin on 29-Oct-2013 00:00

DimBo,

First my apologies for my late reply; I've been working on something else pas few days.

Thank you for the feedbank on the ConfigManager; I'll experiment with this later today.

A question as a result of CustomMultipleChoice solution you presented me with earlier:
I repeated step 4 for all 7 views of the ProfileType_SitefinityProfile (from ViewFrontendCreate through ViewBackendOwnEdit). 
When I edit/add a user in the backend underAdministration>User Management>Users, the CustomMultipleChoice works as expected; storing entered data and displaying it again when the users profile is reopend this way.

However, when I open the current users profile in the Backend (the Profile link next to the Logout lInk
in the upper right corner of the backend), the CustomMultipleChoice' TextBoxes are not rendered in View mode, only the Fields label is displayed.

In edit mode the Checkboxes are rendered, but do not reflect the data entered earlier.
When saving the profile after checking some CheckBoxes the following exception occurs:
Invalid cast from 'System.String' to 'System.String[]'.

What I'm I missing?

Thanx!

Grz. Herman

Posted by Community Admin on 01-Nov-2013 00:00

Hello Herman,

Thank you for getting back to us.

I suggest that the problem might come from the CustomMultipleChoice in the database. If it is stored as array of string (System.String[]), this error could occur. The built-in multiple choice value is stored as String, so try to modify in the settings as Dimitar described below.

Let me know if this helps resolving the problem.

Regards,
Yavor Slavchev
Telerik

Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

Posted by Community Admin on 13-Nov-2013 00:00

Yavor,

Thanks for your reply.

I submitted a support ticket about this issue; so this thread can be considered closed.

Kind regards,
Herman P. Hartog

This thread is closed