0

I have a class which contains a property who's type is another class. For example:

public class Outer
{
    public string SomeStringProperty { get; set; }
    public Inner SomeClassProperty { get; set; }
}

public class Inner
{
    public string InnerProperty1 { get; set; }
    public string InnerProperty2 { get; set; }
}

I want to convert an instance of the Outer class to a URL query string, and include the properties from the nested Inner class.

For example, given an instance of Outer, such as:

Outer toSerialise = new Outer 
{
    SomeStringProperty = "MyOuterValue",
    SomeClassProperty = new Inner
    {
        InnerProperty1 = "MyInnerValue1",
        InnerProperty2 = "MyInnerValue2"
    }
};

I want to convert this to a string of:

&SomeStringProperty=MyOuterValue&InnerProperty1=MyInnerValue1&InnerProperty2=MyInnerValue2

How can I achieve this?


I've found answers to similar questions, however they don't seem to support nested classes.

Potential answer 1 Potential answer 2

devklick
  • 2,000
  • 3
  • 30
  • 47
  • 1
    Tip: when you have the `PropertyInfo` then check the `PropertyType`...if it's not a `String` and it's not `IsPrimitive` then call the same function recursively to accumulate the property values. – Adriano Repetti Feb 21 '20 at 12:26
  • @AdrianoRepetti Good point, thanks! I'm wondering how reliable using `string` and `IsPrimitive` is - Looks like DateTime is *not* primitive, but should probably fall into this category. I wonder if there's any more like this...? – devklick Feb 21 '20 at 14:01
  • To support more data types you have to handle each one (tedious) or check if the object implements `IConvertible` (for the conversion to string) but a few edge cases are there anyway. – Adriano Repetti Feb 21 '20 at 19:12

1 Answers1

0

We had same problem with callback url's client state in Oauth2 because callback urls have ampersand & too

http://.......?param=123&param2=456&state=?id=1&name=test

We just converted callback url to Base64 encoded string and decoded at service itself.

http://.......?param=123&param2=456&state=P2lkPTEmbmFtZT10ZXN0

Fix:

  1. Encode your class instance as json
  2. Encode json as base64string
  3. Send base64string in url as data param
  4. Decode base64 and map json into your model at your api.

JSON:

 { "menu": {
  "id": "file",
  "value": "File",
  "popup": {
    "menuitem": [
      {"value": "New", "onclick": "CreateNewDoc()"},
      {"value": "Open", "onclick": "OpenDoc()"},
      {"value": "Close", "onclick": "CloseDoc()"}
    ]
  }
}}

Base64:

eyJtZW51IjogewogICJpZCI6ICJmaWxlIiwKICAidmFsdWUiOiAiRmlsZSIsCiAgInBvcHVwIjogewogICAgIm1lbnVpdGVtIjogWwogICAgICB7InZhbHVlIjogIk5ldyIsICJvbmNsaWNrIjogIkNyZWF0ZU5ld0RvYygpIn0sCiAgICAgIHsidmFsdWUiOiAiT3BlbiIsICJvbmNsaWNrIjogIk9wZW5Eb2MoKSJ9LAogICAgICB7InZhbHVlIjogIkNsb3NlIiwgIm9uY2xpY2siOiAiQ2xvc2VEb2MoKSJ9CiAgICBdCiAgfQp9fQ==

Url:

&data=eyJtZW51IjogewogICJpZCI6ICJmaWxlIiwKICAidmFsdWUiOiAiRmlsZSIsCiAgInBvcHVwIjogewogICAgIm1lbnVpdGVtIjogWwogICAgICB7InZhbHVlIjogIk5ldyIsICJvbmNsaWNrIjogIkNyZWF0ZU5ld0RvYygpIn0sCiAgICAgIHsidmFsdWUiOiAiT3BlbiIsICJvbmNsaWNrIjogIk9wZW5Eb2MoKSJ9LAogICAgICB7InZhbHVlIjogIkNsb3NlIiwgIm9uY2xpY2siOiAiQ2xvc2VEb2MoKSJ9CiAgICBdCiAgfQp9fQ==

Alternative :

If you must use this query format then you can also use delegate types

Outer toSerialise = new Outer 
{
    SomeStringProperty = "MyOuterValue",
    SomeClassProperty = new Inner
    {
        InnerProperty1 = "MyInnerValue1",
        InnerProperty2 = "MyInnerValue2"
    }
};

var queryObject = new { toSerialise.SomeStringProperty, toSerialise .Inner.InnerProperty1, toSerialise.Inner.InnerProperty2 }
  • This seems like a solution to a rather different problem! – Anoop R Desai Feb 21 '20 at 13:01
  • For Problem "I want to convert an instance of the Outer class to a URL query string, and include the properties from the nested Inner class." -> Json includes properties of nested inner class default. For able to send json in url base64 encoding fix this problem too. At the target site of url he can decode base64 and map json data as class model this fixes the all problem. I dont think its a different problem. – Volkan Dogan Feb 21 '20 at 13:15
  • +1 for thinking outside the box. The problem is that for this to work, you need control over the API that's receiving the request, which might not always be the case. It also involves multiple layers of serialising/deserialising, which would likely have a performance impact. Although I havent tried you're approach, I do expect it to work, but it's far from an ideal solution. – devklick Feb 21 '20 at 16:51