Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • webmonger 130 posts 285 karma points
    Feb 08, 2012 @ 18:49
    webmonger
    0

    Razor 4.7.1.1 DataTypeModel Generic Collection

    Hi

    I've just upgraded an install from 4.7.1 to 4.7.1.1 and all my razor files started to error after searching the forum I found the this post which helped me fix some of the issues. However I'm not sure how to fix one issue I'm still having.

    Some of my models have a csv of ints that either used to be returned as int or List<int> depending on whether they contined commas. They now seem to be returning string which is unhelpful.

    I've added the following to the Umbracosettings.config but it does not seem to have made any difference.

    <mapping nodeTypeAlias="Features">umbraco.MacroEngines.RazorDataTypeModels.IntegerDataTypeModel,umbraco.MacroEngines</mapping>

    Please can you pint me in the right direction.

    Cheers

    Jon

  • Gareth Evans 142 posts 334 karma points c-trib
    Feb 13, 2012 @ 02:23
    Gareth Evans
    1

    Hi Jon

    First off, sorry for the delayed reply.

    I think it's worth clarifying first, why the change was made.

    The change to the parsing was made because sometimes strings which contained , were returned as integers, and other times, as strings.
    In particular, strings that contained a single , (or . if you're in that culture).

    I changed the parsing of the integer type to only automatically apply to a certain data type guids and also modified the razordatatypemodel attribute to be multiple with priorities.

    This RDTM is now used instead of a native int.parse.
    It has a priority of 90, which means it can be overridden by your own model.

    With that in mind, the desired behaviour of a single int or List<int> may be confusing, but all the same, you can create a model to do this.

    What the mapping attribute does it allows you to statically map a given guid or datatype property (field) to a datatype model which otherwise wouldn't handle that guid/property.
    Because properties have a datatype, and that datatype has a guid, normally the RazorDataTypeModel would apply based on the GUID, but people can't modify the data type for Integer (which is shipped with the core)

    However, the functionality of single int or List<int> is not going to be possible with that model anyway.

    You need to create a new model, like so: 

     [RazorDataTypeModel("00000000-0000-0000-0000-000000000000")]
        public class CSVIntegerBinder : IRazorDataTypeModel
        {
            #region IRazorDataTypeModel Members
    
            public bool Init(int CurrentNodeId, string PropertyData, out object instance)
            {
                bool returnSingleItemAsInt = true;
    
                if (PropertyData.Contains(",") || !returnSingleItemAsInt)
                {
                    instance = new CSVInteger(PropertyData);
                }
                else
                {
                    int t = 0;
                    if (int.TryParse(PropertyData, out t))
                    {
                        instance = t;
                    }
                    else
                    {
                        instance = null;
                        return false;
                    }
                }
                return true;
            }
    
            #endregion
        }
        public class CSVInteger : IEnumerable
        {
            private List<int> data;
            public bool Multiple { get { return _multiple; } }
            public bool Single { get { return !_multiple } }
    public int Count { get { return data.Count; } } public int ToInt(){ if(data.Count > 0) { return data.First(); } return 0; } public CSVInteger(string csv) { data = new List<int>(); if (!string.IsNullOrWhiteSpace(csv)) { string[] items = csv.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); if (items.Length > 1) { Multiple = true; } foreach (string item in items) { int t = 0; if (int.TryParse(item.Trim(), out t)) { data.Add(t); } }; } } #region IEnumerable Members public IEnumerator GetEnumerator() { return data.GetEnumerator(); } #endregion #region IEnumerable Members System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return data.GetEnumerator(); } #endregion public List ToList() { return data; } }

    This model will return a single int, or a List<int> if the string contains more than one item.
    This may be confusing though, as you never know whether you will get a single int or a list - so you can't treat it the same all the time.
    For this reason, in the binder, there is an if statement. If you change the boolean at the top (or delete the rest of the single int handling) and always return a CsvInteger object in instance, then I've put a bool Multiple on it so you can handle a single item and get a single int back.

    I would personally always return a CSVInteger.

    You will need to put your data type GUID in the top of the file inside the attribute 

  • webmonger 130 posts 285 karma points
    Feb 13, 2012 @ 10:50
    webmonger
    0

    Hi Gareth

    Thanks for the update, I'll check this out and let you know how I get on.

    Jon

Please Sign in or register to post replies

Write your reply to:

Draft