1-888-365-2779
+1-888-365-2779
Try Now
More in this section

Forums / General Discussions / Using a Custom Interface Widget when creating a Custom Field

Using a Custom Interface Widget when creating a Custom Field

5 posts, 0 answered
  1. Bob Evans
    Bob Evans avatar
    19 posts
    Registered:
    22 Jun 2012
    05 Jan 2011
    Link to this post
    Now that dynamic fields (metafields) have been re-introduced in the Sitefinity 4 RC2 is there any guidance on how to create a custom user control for entering the data?  That is, when creating a dynamic field you can choose "Custom..." for the interface widget and are then prompted for the path of the usercontrol.  How exactly should a developer go about implementing this custom user control?  What interfaces need to be implemented, or what classes within the Sitefinity framework need to be extended?  An example would be great (even if it is a rudimentary one that shows how to do this in the most basic form).
  2. Bob Evans
    Bob Evans avatar
    19 posts
    Registered:
    22 Jun 2012
    06 Jan 2011
    Link to this post
    I'm surprised no one has tried to do this before, so I'm going to bump this with more information.

    What I'm doing is attempting alter the Blog Post entity to add a new custom field, and also specifying my own as the editor.  Since there is no documentation or guidance on how to accomplish this I've been attempting to perform this through trial and error.

    I've created a new class within my Sitefinity solution named 'GenericCustomFieldEditor' that is intended to be the definition of the editor to associated with my custom field.  When choosing 'Custom...' and entering the fully-qualified namespace 'SitefinityWebApp.WebControls.GenericCustomFieldEditor' I initially received an error stating that it did not implement the Telerik.Sitefinity.Web.UI.Fields.Contracts.IField namespace.  I resolved this by having my class extend from Telerik.Sitefinity.Web.UI.Fields.FieldControl, but not when I choose to save my new field from the Sitefinity administration interface I get the following error:

    Index was outside the bounds of the array.

    Which is rather meaningless.  I assume this has to be a problem within the Sitefinity 4 codebase, as the SdrConfigExample.e2e log file reports the extended details as:

    System.IndexOutOfRangeException: Index was outside the bounds of the array.
       at Telerik.Sitefinity.ModuleEditor.Web.Services.Model.DefinitionBuilder.TryGetDefinitionElementType(String fieldType, Type& fieldDefinitionType)
       at Telerik.Sitefinity.ModuleEditor.Web.Services.Model.DefinitionBuilder.CreateDefinitionElement(String fieldType, Object definition, ConfigElement parent, Boolean resolveElementType)
       at Telerik.Sitefinity.ModuleEditor.Web.Services.Model.CustomFieldsContext.CreateDynamicDefinitionElement(WcfCustomField field, ConfigElement parent)
       at Telerik.Sitefinity.ModuleEditor.Web.Services.Model.CustomFieldsContext.SaveFieldDefinition(WcfCustomField field)
       at Telerik.Sitefinity.ModuleEditor.Web.Services.Model.CustomFieldsContext.AddOrUpdateCustomFields(IDictionary`2 fields)
       at Telerik.Sitefinity.ModuleEditor.Web.Services.ModuleEditorService.ApplyChangesInternal(ModuleEditorContext context, String providerName)
       at SyncInvokeApplyChanges(Object , Object[] , Object[] )
       at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
       at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
       at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
       at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
       at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

    I went so far as to use Fiddler to check what exactly was being sent in the WCF server call, and these are the details:

    {"AddFields":
        [{
            "Key":"CustomField",
            "Value":{
                "Name":"CustomField",
                "ContentType":"Long text",
                "FieldTypeKey":"LongText",
                "IsCustom":true,
                "Definition":{
                    "FieldName":"CustomField",
                    "FieldType":"SitefinityWebApp.WebControls.GenericCustomFieldEditor",
                    "FieldVirtualPath":null,
                    "Title":"CustomField",
                    "Example":"",
                    "CssClass":"",
                    "DefaultValue":"",
                    "RenderChoiceAs":3,
                    "MutuallyExclusive":true,
                    "Choices":"",
                    "VisibleViews":[],
                    "Hidden":false,
                    "ValidatorDefinition":{"MinLength":"0"},
                    "TaxonomyId":null
                },
                "DatabaseMapping":{
                    "ClrType":"System.String",
                    "DbType":"CLOB",
                    "DbSqlType":"TEXT",
                    "DbLength":"",
                    "DbPrecision":"",
                    "DbScale":"",
                    "Nullable":true,
                    "Indexed":false,
                    "ColumnName":""
                }
            }
        }],
        "ContentType":"Telerik.Sitefinity.Blogs.Model.BlogPost",
        "DefaultFields":[],
        "RemoveFields":[]
    }

    Nothing suspicious in the JSON sent to the server.  So what's wrong?

    Can any Telerik personnel tell me the following:  Is using a custom editor when creating a custom field currently supported in RC2 (4.0.1030.0)?  If so, what are the basics of getting it working?  If not, when does this plan on being supported?
  3. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    16 Jun 2017
    06 Jan 2011
    Link to this post
    Hello Bob,

    Currently you can add only a custom control ( there are issues when you use a user control). You need to create a custom control that inherits from CompositeFieldControl or completely custom control that implements IField interface.

    sample

    using System;
    using Telerik.Sitefinity.Web.UI.Fields;
      
    namespace Telerik.Sitefinity.Samples
    {
        class CompositeFieldControlCustom : CompositeFieldControl
        {
            protected override System.Web.UI.WebControls.WebControl TitleControl
            {
                get { throw new NotImplementedException(); }
            }
      
            protected override System.Web.UI.WebControls.WebControl DescriptionControl
            {
                get { throw new NotImplementedException(); }
            }
      
            protected override System.Web.UI.WebControls.WebControl ExampleControl
            {
                get { throw new NotImplementedException(); }
            }
      
            protected override void InitializeControls(Web.UI.GenericContainer container)
            {
                throw new NotImplementedException();
            }
      
            protected override string LayoutTemplateName
            {
                get { throw new NotImplementedException(); }
            }
        }
    }


    All the best,
    Ivan Dimitrov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  4. Bob Evans
    Bob Evans avatar
    19 posts
    Registered:
    22 Jun 2012
    06 Jan 2011
    Link to this post
    Hi Ivan -- I tried your solution but still received an IndexOutOfRangeException.

    I don't like to do this because Sitefinity 4 should be a working product, but I opened Reflector and dug through to find why this is occurring.  There appears to be an error with the following static method declared in the Telerik.Sitefinity.ModuleEditor.Web.Services.Model.DefinitionBuilder class.

    01.private static bool TryGetDefinitionElementType(
    02.    string fieldType,
    03.    out Type fieldDefinitionType)
    04.{
    05.    fieldDefinitionType = null;
    06.    Type elementType = TypeResolutionService.ResolveType(fieldType);
    07.    if (elementType.IsArray)
    08.    {
    09.        elementType = elementType.GetElementType();
    10.    }
    11.    FieldDefinitionElementAttribute attribute =
    12.        elementType.GetCustomAttributes(
    13.            typeof(FieldDefinitionElementAttribute), false)[0]
    14.            as FieldDefinitionElementAttribute;
    15.    if (attribute != null)
    16.    {
    17.        fieldDefinitionType = attribute.FieldDefinitionType;
    18.        return true;
    19.    }
    20.    return false;
    21.}

    On like (13) you can see it implicitly attempts to access the element at array index zero.  If the custom class does not have the FieldDefinitionElement attribute applied to its class definition then this call will fail with an IndexOutOfRangeException exception (as was my case), rather than returning FALSE.  Technically it should first test if the GetCustomAttributes call returned an array with a length greater than zero before attempting to access any element at an index.

    For those interested I was able to (sort of) get this working by implementing the following:

    01.using System;
    02.using Telerik.Sitefinity.Web.UI.Fields;
    03.   
    04.namespace Telerik.Sitefinity.Samples
    05.{
    06.    [FieldDefinitionElement(typeof(GenericCustomFieldEditorDefinitionElement))]
    07.    public class CompositeFieldControlCustom :
    08.        CompositeFieldControl
    09.    {
    10.        ...
    11.    }
    12.}

    The key here is line (6) where the class is decorated with an attribute pointing towards my own custom class named GenericCustomFieldEditorDefinitionElement. This 'definition' class class needs:

    a) Inherit from class Telerik.Sitefinity.Web.UI.Fields.Config.FieldControlDefinitionElement
    b) Implement an interface in the namespace Telerik.Sitefinity.Web.UI.Fields.Contracts (for example, Telerik.Sitefinity.Web.UI.Fields.Contracts.ITextFieldDefinition)
  5. Milena
    Milena avatar
    75 posts
    Registered:
    05 Apr 2017
    12 Jan 2011
    Link to this post
    Hello Bob Evans,

    You are right, there should be a check if the GetCustomAttributes call returned an array with a length greater than zero before attempting to access any element with an index.
    The fix will be available in next releases.

    Thanks for your findings! I updated your Telerik points.

    Kind regards,
    Milena
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
5 posts, 0 answered