30

Using mvc i get values like this to avoid class declarations and router changes.

public dynamic Create([FromBody] dynamic form)
{
    var username = form["username"].Value;
    var password = form["password"].Value;
    var firstname = form["firstname"].Value;
...

I like to iterate through all values and check them for null or empty.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
MR.ABC
  • 4,712
  • 13
  • 44
  • 88
  • 1
    s/"I like to"/"I would like to, and don't know how" ? – doctorlove Aug 19 '14 at 13:44
  • 2
    You'd like to avoid class declarations? Why? – Andrew Whitaker Aug 19 '14 at 13:48
  • 1
    @doctorlove Maybe sound better. I'm not sure about your intentions. Go for foreach(var value in form). – MR.ABC Aug 19 '14 at 13:48
  • Use [DTO](http://en.wikipedia.org/wiki/Data_transfer_object) to get the input from Views. It is easy to implement – Felipe Oriani Aug 19 '14 at 13:49
  • What exactly are you wanting to iterate over? The actual properties of your object or does it have an indexer and you just want to check all the things that are indexed? – Chris Aug 19 '14 at 13:50
  • @Andrew Whitaker because i work with javascript and json. This just overhead and make no sense. – MR.ABC Aug 19 '14 at 13:50
  • If you were create a class to represent your incoming form, you could leverage ASP.NET MVC's [built in validation](http://www.asp.net/mvc/tutorials/mvc-5/introduction/adding-validation) and possibly avoid the overhead you're incurring by using `dynamic` here. – Andrew Whitaker Aug 19 '14 at 13:53
  • Just want make method to avoid write 10 times String.IsNullOrWhiteSpace. Something like HaveNullOrWhiteSpaceValues(form) – MR.ABC Aug 19 '14 at 13:53
  • @Andrew Whitaker Believe me this fits better in my workflow. – MR.ABC Aug 19 '14 at 13:54

4 Answers4

39

If you get a json from the argument, you could convert it to an Dictionary<string, dynamic> where the string key is the name of the property and the dynamic is a value that can assume any type. For sample:

var d = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(form);

var username = d["username"];

You also could loop between Keys property from the Dictionary<>:

foreach(var key in d.Keys)
{
   // check if the value is not null or empty.
   if (!string.IsNullOrEmpty(d[key])) 
   {
      var value = d[key];
      // code to do something with 
   }
}
Felipe Oriani
  • 37,948
  • 19
  • 131
  • 194
15

This is quite old, but I came across this and am wondering why the following was not proposed:

var data = (IDictionary<string, object>)form;
xcopy
  • 2,248
  • 18
  • 24
  • that's just what I was looking for! – Dmitry Volkov Jun 27 '17 at 07:18
  • 1
    Probably because of this: Message "Cannot convert type '<>f__AnonymousType0' to 'System.Collections.Generic.IDictionary'" string. – Jay Apr 26 '18 at 13:24
  • 2
    @Jay, if you are receiving that message, you are not casting against a dynamic object but instead trying to cast against an anonymous type which is not the same thing. – xcopy Apr 26 '18 at 14:29
  • I ran the statement with 'dynamic form', just like in the OP. I ended up converting my dynamic to json with JsonConvert and then JsonConverting my json to a Dictionary. That works fine for me. – Jay Apr 26 '18 at 15:02
2

You can use JavaScriptSerializer and dynamic object:

JavaScriptSerializer serializer = new JavaScriptSerializer();

dynamic myDynamicObject = serializer.DeserializeObject(json);

For example, if you want to loop through myDynamicObject["users"]:

foreach (KeyValuePair<string, dynamic> user in myDynamicObject["users"]){
    Console.WriteLine(user.Key+": "+user.Value["username"]);
    Console.WriteLine(user.Key+": "+user.Value["email"]);
}
Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
0

the answers above did not work for me, but that works:

//responseBody is a json string with "settings" key
dynamic dynamicObject = JsonConvert.DeserializeObject<dynamic>(responseBody)!;
var settings = dynamicObject.settings;

var k = 0;
foreach (JProperty item in settings.Children())
    Console.WriteLine($"{k++}. settings - {item.Name}: {item.Value}");
Sasha Bond
  • 984
  • 10
  • 13