Dynamic Content Bug

Vote:
 

I'm creating DC-controls with DynamicContentPlugIn and I use Page type builder and ETF to create editor controls with DynamicContentEditControl. But I have a very annoying bug now with the values in the fields of the control. When I'm using the crontrol and leave a field empty or don't check a checkbox it uses the value from the property below. In other words, the value can't be null because then it uses the value from the next propery in line. 
I am aware of the issue with moving around the order of the properties once they have values, but now the values moves around by them themselves.
Any help solving this would be much appreciated.

 

#60790
Aug 24, 2012 18:12
Vote:
 

use this base class

public class DynamicContentBase : TranslateUserControl, EPiServer.DynamicContent.IDynamicContent, IDynamicContentDisplayType
{
    public bool RenderAsBlockElement { get { return true; } }
    public string Add2Style = "";
    public string PreviewText = "";
    public virtual bool DebugMode { get { return true; } }
    public string DebugText = "";
    #region IDynamicContent Members

    public virtual System.Web.UI.Control GetControl(EPiServer.PageBase hostPage)
    {
        throw new NotImplementedException();
    }

    protected PropertyDataCollection _properties;

    public void SetProperties(PropertyDataCollection props)
    {
        _properties = props;
    }

    public virtual EPiServer.Core.PropertyDataCollection Properties
    {
        get { return _properties; }
    }

    public virtual string Render(EPiServer.PageBase hostPage)
    {
        throw new NotImplementedException();
    }

    public virtual bool RendersWithControl
    {
        get { return true; }
    }

    #region State (64 encoded)

    private string _state;

    public string State
    {
        get
        {
            if (Value == null)
                return null;
            return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(Value));
        }
        set
        {
            if (value != null)
            {
                _state = value;
                byte[] toDecodeByte = Convert.FromBase64String(value);

                System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
                System.Text.Decoder utf8Decode = encoder.GetDecoder();

                int charCount = utf8Decode.GetCharCount(toDecodeByte, 0, toDecodeByte.Length);

                char[] decodedChar = new char[charCount];
                utf8Decode.GetChars(toDecodeByte, 0, toDecodeByte.Length, decodedChar, 0);
                string result = new String(decodedChar);
                Value = result;
            }
        }
    }

    #endregion

    #region Value
    public string MakeStringFromCollection(PropertyDataCollection properties, bool debug)
    {
        if (properties == null)
            return null;
        string result = "";
        XmlDocument doc = new XmlDocument();
        string xml = "<data>";
        foreach (PropertyData prop in properties)
        {
            if (DebugMode && prop.Name.Equals("Debug")) { }
            else
            {
                result += "adding " + prop.Name + System.Environment.NewLine;
                xml += "<" + prop.Name + " />";
            }

        }
        xml += "</data>";
        doc.LoadXml(xml);
        foreach (XmlNode node in doc.FirstChild.ChildNodes)
        {
            if (properties[node.Name] is Itera.Property.PropertyMulitBase)
            {
                node.InnerText = (properties[node.Name] as Itera.Property.PropertyMulitBase).CreateXml();
            }
            else
                node.InnerText = properties[node.Name].ToString();

        }
        result += doc.FirstChild.InnerXml;
        return result;
    }
    public string Value_Set = "";
    public string Value
    {
        get
        {
            return MakeStringFromCollection(Properties, false);

        }
        set
        {
            if (value != null)
            {
                Value_Set += value + "<hr />";
            }
            if (Properties == null)
                return;
            XmlDocument doc = new XmlDocument();
            string xml = "<data>" + value + "</data>";
            doc.LoadXml(xml);
            foreach (PropertyData prop in Properties)
            {
                if (doc.FirstChild[prop.Name] != null)
                {
                    prop.ParseToSelf(doc.FirstChild[prop.Name].InnerText);
                    if (DebugMode)
                        DebugText += "set" + prop.Name + "=(" + doc.FirstChild[prop.Name].ChildNodes + ")" + doc.FirstChild[prop.Name].InnerText + System.Environment.NewLine;
                }
            }
            ValueSet(value);
        }
    }

    #endregion

    #endregion

    public virtual void ValueSet()
    {
    }
    public virtual void ValueSet(string xml)
    {
        ValueSet();
    }
}

    

#60791
Aug 24, 2012 18:31
Vote:
 

Thank you very much!

But if I replace "EPiServer.UserControlBase" with "MyPage.Classes.DynamicContentBase" my propertied disappear. I'm not sure how to implement you class the right way.

Regards

Karl

#60812
Aug 27, 2012 11:29
Vote:
 

Hi

This base class you had to register  the properties by override the Properties method

but if you use this class I quess it will work as you are used to

public class DynamicContentBaseWithAuto : EPiServer.UserControlBase, EPiServer.DynamicContent.IDynamicContent, IDynamicContentDisplayType
{
    public bool RenderAsBlockElement { get { return true; } }
    public string Add2Style = "";
    public string PreviewText = "";
    public virtual bool DebugMode { get { return true; } }
    public string DebugText = "";
    #region IDynamicContent Members

    public virtual System.Web.UI.Control GetControl(EPiServer.PageBase hostPage)
    {
        throw new NotImplementedException();
    }

    protected PropertyDataCollection _properties;

       
    public virtual EPiServer.Core.PropertyDataCollection Properties
    {
        get {

            if (_properties == null)
            {
                var _new = new PropertyDataCollection();
                var type = this.GetType();
                var _propInfo = (
                from pi in type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.SetProperty)
                where pi.PropertyType.IsSubclassOf(typeof(PropertyData)) || pi.PropertyType == typeof(string) || pi.PropertyType == typeof(bool) || pi.PropertyType == typeof(PageReference) || pi.PropertyType == typeof(int)
                select pi into p
                where p.CanRead && p.CanWrite
                select p).ToList<PropertyInfo>();
                foreach (PropertyInfo current in _propInfo)
                {
                    PropertyData propertyData = null;
                    if (current.PropertyType.IsSubclassOf(typeof(PropertyData)))
                    {
                        propertyData = (Activator.CreateInstance(current.PropertyType) as PropertyData);
                    }
                    else
                    {
                        if (current.PropertyType == typeof(string))
                        {
                            propertyData = new PropertyString();
                        }
                        else
                        {
                            if (current.PropertyType == typeof(int))
                            {
                                propertyData = new PropertyNumber();
                            }
                            else
                            {
                                if (current.PropertyType == typeof(bool))
                                {
                                    propertyData = new PropertyBoolean();
                                }
                                else
                                {
                                    if (current.PropertyType == typeof(PageReference))
                                    {
                                        propertyData = new PropertyPageReference();
                                    }
                                }
                            }
                        }
                    }
                    if (propertyData != null)
                    {
                        propertyData.Name = current.Name;
                        _new.Add(propertyData);
                    }
                }
                _properties = _new;
            }
            return _properties; 
        }
    }

    public virtual string Render(EPiServer.PageBase hostPage)
    {
        throw new NotImplementedException();
    }

    public virtual bool RendersWithControl
    {
        get { return true; }
    }

    #region State (64 encoded)

    private string _state;

    public string State
    {
        get
        {
            if (Value == null)
                return null;
            return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(Value));
        }
        set
        {
            if (value != null)
            {
                _state = value;
                byte[] toDecodeByte = Convert.FromBase64String(value);

                System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
                System.Text.Decoder utf8Decode = encoder.GetDecoder();

                int charCount = utf8Decode.GetCharCount(toDecodeByte, 0, toDecodeByte.Length);

                char[] decodedChar = new char[charCount];
                utf8Decode.GetChars(toDecodeByte, 0, toDecodeByte.Length, decodedChar, 0);
                string result = new String(decodedChar);
                Value = result;
            }
        }
    }

    #endregion

    #region Value
    public string MakeStringFromCollection(PropertyDataCollection properties, bool debug)
    {
        if (properties == null)
            return null;
        string result = "";
        XmlDocument doc = new XmlDocument();
        string xml = "<data>";
        foreach (PropertyData prop in properties)
        {
            if (DebugMode && prop.Name.Equals("Debug")) { }
            else
            {
                result += "adding " + prop.Name + System.Environment.NewLine;
                xml += "<" + prop.Name + " />";
            }

        }
        xml += "</data>";
        doc.LoadXml(xml);
        foreach (XmlNode node in doc.FirstChild.ChildNodes)
        {
            if (properties[node.Name] is Itera.Property.PropertyMulitBase)
            {
                node.InnerText = (properties[node.Name] as Itera.Property.PropertyMulitBase).CreateXml();
            }
            else
                node.InnerText = properties[node.Name].ToString();

        }
        result += doc.FirstChild.InnerXml;
        return result;
    }
    public string Value_Set = "";
    public string Value
    {
        get
        {
            return MakeStringFromCollection(Properties, false);

        }
        set
        {
            if (value != null)
            {
                Value_Set += value + "<hr />";
            }
            if (Properties == null)
                return;
            XmlDocument doc = new XmlDocument();
            string xml = "<data>" + value + "</data>";
            doc.LoadXml(xml);
            foreach (PropertyData prop in Properties)
            {
                if (doc.FirstChild[prop.Name] != null)
                {
                    prop.ParseToSelf(doc.FirstChild[prop.Name].InnerText);
                    if (DebugMode)
                        DebugText += "set" + prop.Name + "=(" + doc.FirstChild[prop.Name].ChildNodes + ")" + doc.FirstChild[prop.Name].InnerText + System.Environment.NewLine;
                }
            }
            ValueSet(value);
        }
    }

    #endregion

    #endregion

    public virtual void ValueSet()
    {
    }
    public virtual void ValueSet(string xml)
    {
        ValueSet();
    }
}

    

#60813
Aug 27, 2012 11:40
Vote:
 

And it's a bug in the base class. Or more like bad handy work. Since they use | as seperator and the position of the property to map it back.

My code saves the data down with the name of the property.

#60814
Aug 27, 2012 11:44
Vote:
 

It worked!

Thank you!

#60815
Aug 27, 2012 11:47
Vote:
 

nice of you if you could mark it as solved

#60818
Aug 27, 2012 12:09
Vote:
 

One more question:

Are you using DynamicContentPlugIn or do you register the control in web.config?

I get this error message: "The method or operation is not implemented" on

        public virtual System.Web.UI.Control GetControl(EPiServer.PageBase hostPage)
        {
            throw new NotImplementedException();
        }

 

#60820
Aug 27, 2012 14:26
Vote:
 
public override bool RendersWithControl
        {
            get { return false; }
        }

    

#60825
Aug 27, 2012 19:23
Vote:
 

Then i get the same error message on :

        public virtual string Render(EPiServer.PageBase hostPage)
        {
            throw new NotImplementedException();
        }

What i did to solve the above problem was to add:

        public override System.Web.UI.Control GetControl(EPiServer.PageBase hostPage)
        {
            var userControl = (MagazineItem)hostPage.LoadControl("~/Templates/DynamicContent/MagazineItem.ascx");
            userControl.Title = Properties["Title"].Value as string;
            return userControl;
	}

It takes alot of extra code to write out all the properties again but it works.

#60829
Aug 28, 2012 8:57
Vote:
 

I have not used that base class you are using before, but if you modify above code to some thing like this I quess that mapping will be done fore you

public class DynamicContentBaseWithAuto : EPiServer.UserControlBase, EPiServer.DynamicContent.IDynamicContent, IDynamicContentDisplayType
{
    public bool RenderAsBlockElement { get { return true; } }
    public string Add2Style = "";
    public string PreviewText = "";
    public virtual bool DebugMode { get { return true; } }
    public string DebugText = "";
    #region IDynamicContent Members



    protected PropertyDataCollection _properties;


    public virtual EPiServer.Core.PropertyDataCollection Properties
    {
        get
        {

            if (_properties == null)
            {
                var _new = new PropertyDataCollection();

                foreach (PropertyInfo current in PropertyItems)
                {
                    PropertyData propertyData = null;
                    if (current.PropertyType.IsSubclassOf(typeof(PropertyData)))
                    {
                        propertyData = (Activator.CreateInstance(current.PropertyType) as PropertyData);
                    }
                    else
                    {
                        if (current.PropertyType == typeof(string))
                        {
                            propertyData = new PropertyString();
                        }
                        else
                        {
                            if (current.PropertyType == typeof(int))
                            {
                                propertyData = new PropertyNumber();
                            }
                            else
                            {
                                if (current.PropertyType == typeof(bool))
                                {
                                    propertyData = new PropertyBoolean();
                                }
                                else
                                {
                                    if (current.PropertyType == typeof(PageReference))
                                    {
                                        propertyData = new PropertyPageReference();
                                    }
                                }
                            }
                        }
                    }
                    if (propertyData != null)
                    {
                        propertyData.Name = current.Name;
                        _new.Add(propertyData);
                    }
                }
                _properties = _new;
            }
            return _properties;
        }
    }

    public virtual string Render(EPiServer.PageBase hostPage)
    {
        throw new NotImplementedException();
    }

    public virtual bool RendersWithControl
    {
        get { return true; }
    }

    #region State (64 encoded)

    private string _state;

    public string State
    {
        get
        {
            if (Value == null)
                return null;
            return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(Value));
        }
        set
        {
            if (value != null)
            {
                _state = value;
                byte[] toDecodeByte = Convert.FromBase64String(value);

                System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
                System.Text.Decoder utf8Decode = encoder.GetDecoder();

                int charCount = utf8Decode.GetCharCount(toDecodeByte, 0, toDecodeByte.Length);

                char[] decodedChar = new char[charCount];
                utf8Decode.GetChars(toDecodeByte, 0, toDecodeByte.Length, decodedChar, 0);
                string result = new String(decodedChar);
                Value = result;
            }
        }
    }

    #endregion

    #region Value
    public string MakeStringFromCollection(PropertyDataCollection properties, bool debug)
    {
        if (properties == null)
            return null;
        string result = "";
        XmlDocument doc = new XmlDocument();
        string xml = "<data>";
        foreach (PropertyData prop in properties)
        {
            if (DebugMode && prop.Name.Equals("Debug")) { }
            else
            {
                result += "adding " + prop.Name + System.Environment.NewLine;
                xml += "<" + prop.Name + " />";
            }

        }
        xml += "</data>";
        doc.LoadXml(xml);
        foreach (XmlNode node in doc.FirstChild.ChildNodes)
        {
            if (properties[node.Name] is Itera.Property.PropertyMulitBase)
            {
                node.InnerText = (properties[node.Name] as Itera.Property.PropertyMulitBase).CreateXml();
            }
            else
                node.InnerText = properties[node.Name].ToString();

        }
        result += doc.FirstChild.InnerXml;
        return result;
    }
    public string Value_Set = "";
    public string Value
    {
        get
        {
            return MakeStringFromCollection(Properties, false);

        }
        set
        {
            if (value != null)
            {
                Value_Set += value + "<hr />";
            }
            if (Properties == null)
                return;
            XmlDocument doc = new XmlDocument();
            string xml = "<data>" + value + "</data>";
            doc.LoadXml(xml);
            foreach (PropertyData prop in Properties)
            {
                if (doc.FirstChild[prop.Name] != null)
                {
                    prop.ParseToSelf(doc.FirstChild[prop.Name].InnerText);
                    if (DebugMode)
                        DebugText += "set" + prop.Name + "=(" + doc.FirstChild[prop.Name].ChildNodes + ")" + doc.FirstChild[prop.Name].InnerText + System.Environment.NewLine;
                }
            }
            ValueSet(value);
        }
    }

    #endregion

    #endregion

    public virtual void ValueSet()
    {
    }
    public override Control GetControl(PageBase hostPage)
    {
        Control control;

        if (string.IsNullOrEmpty(ControlUrl))
        {
            throw new ArgumentException("No ViewUrl has been set for this dynamic content user control. The ViewUrl must be set explicitly, e.g.: [DynamicContentPlugIn(ViewUrl = \"~/Path/To/My/UserControl.ascx\")]");
        }
        control = hostPage.LoadControl(UriSupport.ResolveUrlBySettings(ControlUrl));

        this.InitializeControlState(control);
        return control;
    }
    List<PropertyInfo> _propertyItems;
    List<PropertyInfo> PropertyItems
    {
        get
        {
            if (_propertyItems == null)
            {
                var type = this.GetType();
                _propertyItems = (
                        from pi in type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.SetProperty)
                        where pi.PropertyType.IsSubclassOf(typeof(PropertyData)) || pi.PropertyType == typeof(string) || pi.PropertyType == typeof(bool) || pi.PropertyType == typeof(PageReference) || pi.PropertyType == typeof(int)
                        select pi into p
                        where p.CanRead && p.CanWrite
                        select p).ToList<PropertyInfo>();
            }
            return _propertyItems;
        }
    }
    string _controlUrl;
    public string ControlUrl
    {
        get
        {
            if (_controlUrl == null)
            {
                var type = this.GetType();
                DynamicContentPlugInAttribute dynamicContentPlugInAttribute = (DynamicContentPlugInAttribute)type.GetCustomAttributes(typeof(DynamicContentPlugInAttribute), true).First<object>();
                _controlUrl = dynamicContentPlugInAttribute.ViewUrl;
            }
            return _controlUrl;

        }
    }

    protected virtual void InitializeControlState(Control control)
    {

        foreach (PropertyInfo current in PropertyItems)
        {
            PropertyData propertyData = Properties[current.Name];
            if (propertyData != null && propertyData.Value != null)
            {
                try
                {
                    if (current.PropertyType.IsSubclassOf(typeof(PropertyData)))
                    {
                        current.SetValue(control, propertyData, null);
                    }
                    else
                    {
                        current.SetValue(control, propertyData.Value, null);
                    }
                }
                catch
                {
                }
            }
        }
    }
    public virtual void ValueSet(string xml)
    {
        ValueSet();
    }
}

    

#60830
Aug 28, 2012 9:11
Vote:
 

Very nice, thank you again!

#60850
Aug 28, 2012 14:10
This thread is locked and should be used for reference only. Please use the Episerver CMS 7 and earlier versions forum to open new discussions.
* 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.