4

I have a C# view class such as this:

public class DataObject
{
    public int Number { get; set; }
    public dynamic Data { get; set; } // <-----
}

being used in an MVC method like this

[HttpPost]
public ActionResult SaveData(DataObject request) {}

The problem is that I want to recieve multiple types of objects in the Data property of the DataObject class.

That is, I want both these to work as valid input json objects.

Type 1

{
   Number: 1, 
   Data: {
      Text: "a text"
   }
}

Type 2

{
   Number: 2, 
   Data: {
      Value: 1,
      Options: { 1, 2, 3, 4 }
   }
}

Is there a way of doing this with either dynamic objects or some other type of json library magic (just making the property dynamic did nothing)?

All i want to do is store this data in a SQL column nvarchar field and return at a later time (through Entity Framework).

An alternate solution would be to create a view model for each type of input but as there will be 100's of variants to it creating all these views and the corresponding input methods would be cumbersome to maintain.

Adding more details as per comment request: The method is called through Angular.

pub.Save = function (jsonData) {
    return $http(
            {
                method: "POST",
                url: baseURL + "/Save",
                data: { request: jsonData}, // tried this for string
                // data: jsonData, // original way
                timeout: 30000
            }
        )
        .then(function (result) {
            return result.data;
        });
}
JensB
  • 6,663
  • 2
  • 55
  • 94
  • Just accept string and convert it later, so can accept any Json string right ? – Krishna Apr 21 '17 at 06:38
  • Just setting Data as a string propert fails to catch the values. It is always null. – JensB Apr 21 '17 at 06:39
  • Not the data the whole method input like SaveData(string jsonstring) – Krishna Apr 21 '17 at 06:40
  • @Krishna Tried changing the input paramater to a string `public ActionResult SaveData(string request)` but request is always `null` when I do this. – JensB Apr 21 '17 at 06:52
  • How do you pass data ? – Krishna Apr 21 '17 at 06:56
  • @Krishna see update, using Angular. – JensB Apr 21 '17 at 07:01
  • All you are describing here perfectly sounds like node.js with mongodb is perfect for your scenario. – Rob Apr 21 '17 at 07:04
  • see this answer... https://stackoverflow.com/questions/30957248/how-to-send-post-in-angularjs-with-multiple-params/30957308#30957308 When you receive the property at the server side, deserialize the json to extract dynamic inner properties.. deserialize using Newtonsoft json library. – Sajal Apr 21 '17 at 07:10
  • @Robert I dont want to use node.js, I prefer a real typed serverside language that gives propper formatting errors and is more strict on what you can and cannot do / **shots fired** / – JensB Apr 21 '17 at 07:14
  • 1
    @JensB: That's why this was a comment and not an answer ;) – Rob Apr 21 '17 at 07:15
  • @SajalS I might be missing something but that does not seem to describe how to handle a variable in the DTO containing multiple different types of variables without defining them all beforehand. – JensB Apr 21 '17 at 07:18
  • Your method parameter is request but in post you are passing test, can you see the posted data using fiddler or firebug? – Krishna Apr 21 '17 at 08:00
  • @Krishna that is just a copy paste error, the actual code matches (and I have fixed code above now). – JensB Apr 21 '17 at 08:11
  • what's request body in developer tools ? you checked that ? – Krishna Apr 21 '17 at 08:12

2 Answers2

1

At the server side, DTO class must match with the same property name which the payload is carrying.

public class DataObject
{
    public string test { get; set; } // <-----
}

So, your save method remains the same:

[HttpPost]
public ActionResult SaveData(DataObject request) {}

The payload json is in the object request.test but its seralized. Deseralize it using Json Library.

How is it handling multiple different types of variables?

Deseralize it to a dynamic type as:

dynamic obj = JsonConvert.DeserializeObject(request.test, typeof(object));

//Properties within the obj are checked at run time.
if(obj.Text != null) {
  //Do your thing
}

if(obj.Value != null) {
  //Do your thing
}

if(obj.Options != null) {
  //Do your thing
}
Sajal
  • 4,359
  • 1
  • 19
  • 39
0

By converting the data to a JSON string on the client side I was able to send it to the string property and thus being able to use the same typed view for all objects.

I ended up doing this when saving the object (I'm using angular on the front end), converting the Json object to a string.

entry.Data = angular.toJson(entryData.Data, false);

And then when getting the json string back from MVC I did this to get it back to a real javascript object.

entry.Data = angular.fromJson(entry.Data);

MVC would not accept the JSON object into the text property without making it into a json string first.

Using the above method I am storing data like this in my database:

"{\"Value\":123,\"Currency\":\"EUR\"}"
JensB
  • 6,663
  • 2
  • 55
  • 94