1

this.CurrentComponent.ExtendedProperties is a Dictionary<string, string> returned from .Net. When I try and read the values within the Dictionary on the client side, in the javascript, I get all objects of the property, and I do not want that.

I have the following code to populate an object and push to an array in Javascript.

this.populateExtendedProps = function () {
    if (this.CurrentComponent.ExtendedProperties != null) {
        $.each(this.CurrentComponent.ExtendedProperties, function (key, value) {
            debugger;
            var data = {};
            data.Key = key;
            data.Value = value;
            data.Id = key + "_" + value; //generate
            result.push(data);
        });
    }
};

This is what the this.CurrentComponent.ExtendedProperties object looks like: enter image description here All I want is to return the FirstName in the key, and the FirstValue in the value to the callback, but I get the event: object etc as well, and this is not what I want.

How can I only return the actual values that is within the Dictionary, and not all of the memnbers/properties/functions of the javascript object?

UPDATE

Here is the the Object I am returning from the server side, .Net. As can be seen here, the ExtendedProperties Property is a Dictionary<string, string>

public class ComponentItem 
{
    public Guid ItemId { get; set; }
    public Guid ComponentId { get; set; }
    public Guid? ParentItemId { get; set; }
    public string Name { get; set; }
    public int Rank { get; set; }
    public string Text { get; set; }
    public string Description { get; set; }
    public string URL { get; set; }
    public ComponentRendering OpenIn { get; set; }
    public string Property1 { get; set; }
    public string Property2 { get; set; }
    public bool ActiveOnPreview { get; set; }
    public bool ActiveOnLive { get; set; }
    public Guid RepositoryId { get; set; }
    public string RepositoryPath { get; set; }
    public string CDNUrl { get; set; }
    public bool CanDisableInLive { get; set; }
    public bool CanDelete { get; set; }
    public Dictionary<string, string> ExtendedProperties { get; set; }

}

This ComponentItem class, is returned to the front end in response to a Ajax call.

This ExtendedProperty value is received from the Database, as a JSON string, as follow: {"FirstName":"FirstValue"}

I use the following piece of code, to deserialize this JSON string into a Dictionary, as follow:

private Dictionary<string, string> GetExtendedPropertiesFromJson(string extendedPropertiesJson)
    {
        return JsonConvert.DeserializeObject<Dictionary<string, string>>(extendedPropertiesJson);
    }
monstertjie_za
  • 7,277
  • 8
  • 42
  • 73
  • You want to restrict the details at the server side or you want to check the firstname of the object at the client side before executing the loop – Naveen K N Apr 27 '17 at 17:09
  • I haven't worked in .NET so I'm not sure what exactly is happening server-side, but it seems unfortunate that they don't put the "real" data off into its own property, since obviously when this gets to JS it's a regular object with properties, not a Dictionary... You could certainly whitelist the values you expected by comparing them with the key before pushing, but that's a pain, obviously. – Benjamin Robinson Apr 27 '17 at 17:11
  • Do you only want the `FirstName` property, or the `uid` as well? – krillgar Apr 27 '17 at 17:14
  • as I've seen in your picture, this.CurrentComponent.ExtendedProperties is not an a list/array. are you sure that this is an array? – Jeric Cruz Apr 27 '17 at 17:16
  • @JericCruz it's an object, but $.each also handles that: http://api.jquery.com/jquery.each/ – Benjamin Robinson Apr 27 '17 at 17:26

4 Answers4

1

Quick and dirty would be to check the type of value, however that could give you too much if you add more properties.

this.populateExtendedProps = function () {
    if (this.CurrentComponent.ExtendedProperties != null) {
        $.each(this.CurrentComponent.ExtendedProperties, function (key, value) {
            if (typeof (value) === 'string') {
                debugger;
                var data = {};
                data.Key = key;
                data.Value = value;
                data.Id = key + "_" + value; //generate
                result.push(data);
            }
        });
    }
};
krillgar
  • 12,596
  • 6
  • 50
  • 86
  • I thought that was what they meant by "FirstName in the key", with it being a typo of "and the key". If you're correct in your assessment of the question, then yes, this is not correct. – krillgar Apr 27 '17 at 17:14
  • Yeah, I'm not sure... they don't say if that's supposed to be a Dictionary item or not. I was inferring it might not be since FirstName is capitalized camel case and uid isn't – Benjamin Robinson Apr 27 '17 at 17:29
  • I have updated my question. The object returned to Javascript from server, contains the property ExtendedProperties. This is a dictionary being returned. – monstertjie_za Apr 27 '17 at 18:06
0

This isn't really the best solution since it means you have to account for expected keys and you can't just add new ones to the server-side at any time without also updating the client to allow them, but depending on how many possible keys there are, you could 'whitelist' the ones you wanted to allow, and only push those:

this.populateExtendedProps = function () {

    // List of properties you expect and want
    // to allow into the final list of results.
    var allowedProps = {
      FirstName: true, 
      FooKey: true, 
      BarKey: true
    };

    if (this.CurrentComponent.ExtendedProperties != null) {
        $.each(this.CurrentComponent.ExtendedProperties, function (key, value) {
            debugger;

            if (key in allowedProps) {
              var data = {};
              data.Key = key;
              data.Value = value;
              data.Id = key + "_" + value; //generate
              result.push(data);
            }
        });
    }
};

As I mentioned above, I'm not that familiar with .NET so I'm not sure what happens server-side. As Naveen says, maybe there's a way you can trim everything but the actual Dictionary items before it gets to the client. That would obviously be a better solution... then you wouldn't have to worry about these "internal" properties getting mixed in with your data.

  • I see what you are trying to suggest, but I would not think this is a good solution for my needs. Extended properties will eventually contain hundreds of key/value pairs, and this would mean I need to update everytime a new key is added. Thanks for your effort, I appreciate it – monstertjie_za Apr 27 '17 at 18:10
  • Yeah -- like I said, this wasn't really a great solution because of that inflexibility. Unfortunately, since you're dealing with a plain object, it's hard to scrub stuff out unless there's some kind of pattern to the keys or values that's consistent. Glad you solved it! – Benjamin Robinson May 01 '17 at 16:36
0

Without more information on the server-side of your .NET application, there is really no best solution to this question. If you could update the question with more details in how you send a response to your front-end framework would be a great start. Without these information, I will assume a lot of things in my answer.

First off, I will assume that you have full control over your server-side code, and can change the code base at ApiController/Controller level. I will also assume that you are using .NET MVC framework. Finally, I will assume that you are sending a JSON response back. If you are using XML to send responses to your front-end framework, then this answer does not apply.

Within your .NET ApiController/Controller(s) you can exclude properties that you don't want to include in the JSON response. It's as easy as the following code:

[JsonIgnore]
public int Foobar { get; set; }

The above [JsonIgnore] (data annotation) will force .NET JSON response handler to ignore the state when serializing an object (in your case Dictionary<string, string>).

More details can be found on this answer.

Community
  • 1
  • 1
ryan.seo
  • 36
  • 3
  • @monstertjie_za Based on your updated question, since `JsonConvert.DeserializeObject<>` does not add any obscure variables, I believe `_events` object is not being added at the server level. Can you actually see `_events` object in your `ExtendedProperties` when you are debugging in .NET? What about in your `HttpContext.Response`? – ryan.seo Apr 27 '17 at 18:21
  • No not all, while debugging in .Net, my dictionary only contains the valid key:value retrieved from the database – monstertjie_za Apr 27 '17 at 18:28
  • @monstertjie_za Then, `_events` should not be added at the server level. Is it possible that these values are coming from an application framework in the front-end (meteor/vuejs/angular/react/etc.)? Many application frameworks auto-inject the objects they need in runtime. – ryan.seo Apr 27 '17 at 21:48
0

Why I was not getting only the Dictionary items back in the client side, is still a mystery to me, which I will investigate and update this answer with when I find the solution.

For now, I changed my populateExtendedProps function, and created a new server side WebMethod that returns a fresh list of ExtendedProperties.

Here is my server side code:

[WebMethod]
    public Dictionary<string, string> GetExtendedPropertiesForComponentItem(Guid componentItemId)
    {
        return Api.ComponentManager.GetComponentItem(componentItemId).ExtendedProperties;
    }

And my updated Javascript code:

this.populateExtendedProps = function () {
    ajax.request(this.baseUrl + "GetExtendedPropertiesForComponentItem", { componentItemId: this.CurrentComponent.ItemId }, this.populateExtendedPropsSuccess);
};

this.populateExtendedPropsSuccess = function (resp) {
    var collection = [];
    if (resp != null) {
        $.each(resp, function (key, value) {
            var data = {};
            debugger;
            data.Key = key;
            data.Value = value;
            data.Id = key + "_" + value; //generate
            collection.push(data);
        });
        scope.onSaveExtendedPropertySuccess(collection);
    }
}

So the populateExtendedProps function does an ajax post to the server, and calls the the populateExtendedPropsSuccess on successfully returning from the server, and passes the response, and then I loop through the response.

monstertjie_za
  • 7,277
  • 8
  • 42
  • 73