2

object with additional properties from json-like notation string should created. Method will called from Razor view to pass colmodel to jqgrid as json object like

@Html.Raw( Json.Encode( Model.GetColModel()))

Method should have signature like

object GetColModel(string colName, int colWidth, string additonalProperties)

For example,

GetColModel("customer", 17, "address=\"Toronto\", index=1555" )

should return object

new { colName="customer", colwidth=17, address="Toronto", index=1555 }

There may be nested properties like in JSON, eq.

GetColModel("customer", 17, "formatoptions= new { formatter=\"number\", editable=true } " )

should return object

new { colName="customer", colwidth=17, formatoptions=new {
                   formatter="number", 
                   editable=true
                   }
}

I tried method

    public object GetColModel(string colName, int colWidth, string additonalProperties)
    {
        return new
        {
            name = colName,
            width = colWidth,
            &addtitionalProperties
        };
    }

but this fails since macros are not supported in C#

How to create such method or other way to add properties from database to json strung in Razor view ?

It is called from ASP.NET/Mono C# MVC 4 viewmodel. Razor views and RazorEngine are used.

Andrus
  • 26,339
  • 60
  • 204
  • 378

2 Answers2

0

There is nothing built in to do this, but you parse your string using string (string.Split will let you split on ',' but if you might have those in your text you will have to build a real parser, or switch you string format to something like CSV where you can find lots of parsers out there. You might be able to find a property parser for simple syntax. Or you push your additional properties string as json and use Json.net to parse.

Once you have your string parsed into a key/value structure, then you can use ExpandoObject to populate your final object and return that.
https://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject(v=vs.110).aspx

Cleverguy25
  • 493
  • 3
  • 14
  • I can pass additional properties as json string and create .NET object from it using Json.Net parser. How to add those properties to returned object? Is there some sample how to use expando object for this ? – Andrus Jan 31 '16 at 11:02
  • No specific examples, but the point of Expando is you can add properties dynamically. – Cleverguy25 Feb 01 '16 at 06:54
0

Here is a naive implementation of a true json based solution.
You can invoke it using:

dynamic d = Model.GetColModel("customer", 17, " { formatoptions : { formatter : \"number\", editable :true }, stam :2}");

Implementation:

static class ModelExtension
{   
    public static dynamic GetColModel(this Model model, string colName, int colWidth, string additonalProperties) {
        dynamic expando = new ExpandoObject();
        var json = JsonConvert.DeserializeObject<JObject>(additonalProperties);

        expando.name = colName;
        expando.width = colWidth;

        return new FromPropertiesDynamicObjectCreator(expando, json);
    }

    private class FromPropertiesDynamicObjectCreator : DynamicObject
    {
        private readonly dynamic expando = null;

        public FromPropertiesDynamicObjectCreator(IDictionary<string, object> expando, JObject props = null) {
            this.expando = expando;

            if (props != null) {
                ((dynamic)this).props = props;
            }
        }

        public override bool TrySetMember(SetMemberBinder binder, object value) {
            if (binder.Name.Equals("props")) {
                var jsonObj = value as JObject;
                JToken current = jsonObj.First;
                var dictionary = expando as IDictionary<string, object>;

                RecurseJson(current, dictionary);
                return true;
            }

            return false;
        }

        private void RecurseJson(JToken current, IDictionary<string, object> dictionary) {
            JToken value;
            Dictionary<string, object> newDictionary;

            while (current != null) {
                var children = current.Children().ToList();

                foreach (var child in children) {
                    switch (child.Type) {

                        case JTokenType.Object:
                        case JTokenType.Array:
                            newDictionary = new Dictionary<string, object>();
                            dictionary[child.Path] = newDictionary;
                            RecurseJson(child, newDictionary);
                            break;

                        case JTokenType.Property:
                            var prop = ((JProperty)child);
                            value = prop.Value;

                            if (value.HasValues) {
                                newDictionary = new Dictionary<string, object>();
                                dictionary[prop.Name] = newDictionary;
                                RecurseJson(child, newDictionary);
                                break;
                            }
                            dictionary[prop.Name] = ((dynamic)value).Value;
                            break;

                        default:
                            var val = ((dynamic)child).Value;

                            if (val is JToken) {
                                dictionary[child.Path] = val.Value;
                            }
                            else {
                                dictionary[child.Path] = val;
                            }

                            break;
                    }
                }

                current = current.Next;
            }
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result) {
            object value;
            var dictionary = expando as IDictionary<string, object>;

            if (dictionary.TryGetValue(binder.Name, out value)) {
                var innerDictionary = value as IDictionary<string, object>;

                if (innerDictionary != null) {
                    result = new FromPropertiesDynamicObjectCreator(innerDictionary);
                }
                else {
                    result = value;
                }
                return true;
            }

            result = null;
            return true;
        }
    }
}
Sagi
  • 8,972
  • 3
  • 33
  • 41