Using a Custom Interface Widget when creating a Custom Field

Posted by Community Admin on 03-Aug-2018 17:13

Using a Custom Interface Widget when creating a Custom Field

All Replies

Posted by Community Admin on 05-Jan-2011 00:00

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).

Posted by Community Admin on 06-Jan-2011 00:00

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?

Posted by Community Admin on 06-Jan-2011 00:00

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

Posted by Community Admin on 06-Jan-2011 00:00

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)

Posted by Community Admin on 12-Jan-2011 00:00

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

This thread is closed