locked
Having trouble extracting value from anonymous type

    Question

  • As you can see below, I am getting returned an anonymous type (I think) which is of type JsonResult.  In the debugger, I can see all the properties I want, but I can't figure out an easy way to get them in my c# code. 

    I basically want:  result.Data.rows[0].FolderPairName

    Thoughts?

    reflection
    http://peterkellner.net/misc/anon.png

    Peter Kellner http://peterkellner.net Microsoft MVP • ASPInsider
    Friday, May 14, 2010 6:44 AM

Answers

All replies

  • I think that if you declare a global (or local, depending on your needs) variable and set it to result.Data.rows[0].FolderPairName in that particular place in the program then you will get the value that you are looking for.

    So basically, you'll have something like this:

    StringVar = result.Data.rows[0].FolderPairName;

    This should work as long as you set the value from result.Data.rows[0].FolderPairName while it is still in scope. I'm assuming you were stepping through you code when you took that screenshot. The idea here is that if you are able to see the value of a variable or a property during debugging when you are on a specific line in your code then you should be able to access or read that value programatically when your code is executing and gets to that line.

    And, of course, you don't really need a temporary variable as you should be able to use result.Data.rows[0].FolderPairName directly, as long as you use them in the correct space. That was just so you can preserve it in a variable that would not go out of scope easily.

    To be honest, I am not sure why you were having any difficulty in the first place. I appologize if I misunderstood and this wasn't what you wanted to do.

    Good luck!

    Friday, May 14, 2010 5:33 PM
  • The returned value (of type JsonResult) and defined as follows has a "public object Data" in it.

    namespace System.Web.Mvc
    {
      public class JsonResult : ActionResult
      {
        public Encoding ContentEncoding { get; set; }
        public string ContentType { get; set; }
        public object Data { get; set; }
        public JsonRequestBehavior JsonRequestBehavior { get; set; }
        public override void ExecuteResult(ControllerContext context);
      }
    }

    I can debug into that object and in the debugger (as shown below) see the typed data, but I can not access it before it's running because it's of type (object) and I assume it's created as an annoymous type in another section of the program. (I'm pasting that below also)

    public ActionResult Get(FormCollection form)
        {
          var query = new FolderPairQuery();
          if (form["query"] != null)
          {
            query = form["query"].FromJson<FolderPairQuery>();
          }
    
          if (form["start"] != null && form["limit"] != null)
          {
            query.Start = Convert.ToInt32(form["start"]);
            query.Limit = Convert.ToInt32(form["limit"]);
          }
    
          var results = FolderPairManager.I.Get(query);
          return Json(new
                  {
                    success = true,
                    rows = results,
                    total = query.OutputTotal
                  }, JsonRequestBehavior.AllowGet);
        }

    So, how can I access the data in the anonymous returned type "rows" for example.

     

    problem picture

    Thanks...


    Peter Kellner http://peterkellner.net Microsoft MVP • ASPInsider
    Friday, May 14, 2010 5:51 PM
  • Get rid of the Anonymous Methods.  They are not necessary and provide no performance gain.

    Mark the best replies as answers. "Fooling computers since 1971."
    Friday, May 14, 2010 6:38 PM
    Moderator
  • Hi,

    Did you try to getting the value by reflection? if so, what was the result?

    Thank you.


    WHAT'S NEW IN THE .NET FRAMEWORK 4:
    Article: Comparison of parallel and sequential computing in .NET Framework
    Friday, May 14, 2010 6:46 PM
  • Just to make clear what you suggesting, I did remove the anonymous method and it of course worked because everything becomes strongly typed.  The reason I want to use anonymous type is so that I can add extra parameters to my return without having to update the typed class definition.

    What I'm hoping for is some very nice c# syntax that lets me access data associated with annonyous data. I've been playing with the keyword "dynamic" in .net 4 and have not figured out the magic.  I've also been playing with a clever Cast trick (http://tomasp.net/blog/cannot-return-anonymous-type-from-method.aspx) with not much luck.

    I'd love to understand how to better deal with anonymous data since it's so powerful.  Any suggestions would be appreciated.

     using (var controller = new FolderPairController())
          {
            var result = (JsonResult)controller.Get(formGet);
    
            List<FolderPairResult> folderPairResultsRet =
              ((ReturnClassNotAnnoymous) result.Data).rows;
     public class FolderPairResultData
      {
        public bool success { get; set; }
        public int total { get; set; }
        public List<FolderPairResult> rows { get; set; }
      }

    Peter Kellner http://peterkellner.net Microsoft MVP • ASPInsider
    Friday, May 14, 2010 6:58 PM
  • I tried reflection and didn't figure out the syntax. I was really hoping for a .net 4. type solution that would be clean. I'm sure eventually I would have figured out the reflection syntax but I'm never good at that.
    Peter Kellner http://peterkellner.net Microsoft MVP • ASPInsider
    Friday, May 14, 2010 6:59 PM
  • It's really odd!

    Unfortunately, I don't have JSON. does this problem exist in .NET Framework itself too? I want to try here a same sample code if it's possible.

    Thank you.


    WHAT'S NEW IN THE .NET FRAMEWORK 4:
    Article: Comparison of parallel and sequential computing in .NET Framework
    Friday, May 14, 2010 7:13 PM
  • For questions related to ASP.NET use the ASP.NET forum .

    You should ask questions related to the System.Web.Mvc namespace there as well.

    Rudy  =8^D


    Mark the best replies as answers. "Fooling computers since 1971."
    Friday, May 14, 2010 7:16 PM
    Moderator
  • I'm asking this question as a c# issue, not an MVC issue.  The topic is annonymous types, reflection, dynamic, etc.  This really is not an MVC specific questions.  The example just happens to be from an MVC project, but it could be any project.

    I'm hoping for c# wizards to help me out and I thought this was the correct forum for that.


    Peter Kellner http://peterkellner.net Microsoft MVP • ASPInsider
    Friday, May 14, 2010 7:20 PM
  • I'm just curious what would happen if you got rid of the cast in var result = (JsonResult)controller.Get(formGet) and used var result = controller.Get(formGet)? Would that work, and, if so, would it have any effect on the actual value of result?

    However, and this might be probably pretty useless but have you tried using an explicit declaration (i.e. JsonResult result =  (JsonResult)controller.Get(formGet) or even JsonResult result = controller.Get(formGet) )?

    Could you also clarify what you meant in this sentence:

    "I can debug into that object and in the debugger (as shown below) see the typed data, but I can not access it before it's running..."

    What exactly did you mean by *before* it's running?

    Edit: definitely NOT the answer yet.

    Friday, May 14, 2010 7:21 PM
  • GonzoKinght,

    You did it!  I guess I had forgotten to take the cast out in one of my earlier attemps.  The code below works perfectly without having to resort to reflection or dynamic.

    You are my hero for the day. Thank's very much (and thanks to RudeDog2 also).

     

     dynamic result = controller.Get(formGet);
            var o = result.Data;
            List<FolderPairResult> myRows = (List<FolderPairResult>) o.rows; 

    Peter Kellner http://peterkellner.net Microsoft MVP • ASPInsider
    Friday, May 14, 2010 7:37 PM
  • Edit: I see. Let's think about this some more.

    Friday, May 14, 2010 7:45 PM
  • Actually, I spoke too soon.  In my testing, I forgot to turn the return back to an annoymous type (as follows)

     var results = FolderPairManager.I.Get(query);
          return Json(new // ReturnClassNotAnnoymous
                  {
                    success = true,
                    rows = results,
                    total = query.OutputTotal
                  }, JsonRequestBehavior.AllowGet);

    When I did that (by putting the comment in after (new it does not work again.

    To clarify what I meant by "I can debug into..", what I mean is that the debugger let's me drill into anonymous type data because it's looking at the data runtime.  When I write the code, the intellisense does not allow me to specify properties that are returned by anonymous data.  "Before it's running" means before the dynamic data is created when the program is executing.


    Peter Kellner http://peterkellner.net Microsoft MVP • ASPInsider
    Friday, May 14, 2010 7:46 PM
  • I'm asking this question as a c# issue, not an MVC issue.  The topic is annonymous types, reflection, dynamic, etc.  This really is not an MVC specific questions.  The example just happens to be from an MVC project, but it could be any project.

    I'm hoping for c# wizards to help me out and I thought this was the correct forum for that.


    Peter Kellner http://peterkellner.net Microsoft MVP • ASPInsider


    I disagree.  Your issue is with a type within the System.Web.Mvc namespace.  The "C# Wizards" answer is to get rid of the anonymous method, which fixes the problem.  You are not using anonymous methods properly, anyway. 

    One should never expect your code to be able to reference the object instances.  It can be done at great expense in CPU time in some cases through Reflection. 

    Not many participants on this forum have that library to test your code.  Please use the proper forum for advice on that type.  Or, please present an example that does not use the MVC Framework.

    Thanks, ahead of time.  Rudy  =8^D


    Mark the best replies as answers. "Fooling computers since 1971."
    Friday, May 14, 2010 7:48 PM
    Moderator
  • To clarify what I meant by "I can debug into..", what I mean is that the debugger let's me drill into anonymous type data because it's looking at the data runtime.  When I write the code, the intellisense does not allow me to specify properties that are returned by anonymous data.  "Before it's running" means before the dynamic data is created when the program is executing.

    Thank you, that does clarify everything for me.

    Now, correct me if I'm wrong here but just because Intellisense doesn't know what the contents are before the program is being run (not suprising since the actual type will be resolved at run time) doesn't mean that you would not be able to access the contents of result.Data.rows[0].FolderPairName at runtime, does it? My logic here is that if the object does get instantiated properly at run time then you should be able to get the result... but clearly that's not the case.

    Stil, if you were getting a warning from the compiler then if you were to go ahead and use that statement anyway, maybe putting that portion of the code inside of the try block might make it happy?

    Can't quite seem to figure out what the solution might be... Right now I'm thinking that you either need to use generics to instantiate your object or to either declare it or cast it as obj. I will try to think about this some more as I feel that I'm being too confusing.

    By the way, in case this topic does get moved before I see the response, I hope you get your issue resolved, Peter.

    Friday, May 14, 2010 8:17 PM
  • Thanks GonzoKnight.

    The solution does not compile with result.Data.rows..   That is why I feel like there is some hope for the dynamic c# syntax. Hopefully, I'll get an answer from that.


    Peter Kellner http://peterkellner.net Microsoft MVP • ASPInsider
    Friday, May 14, 2010 8:21 PM
  • I followed Yasser's advice above and used reflection.  I wrote a post about the entire solution on my blog so hopefully, if anyone gets this far, they can see the final answer.

    http://peterkellner.net/2010/05/14/unit-test-jsonresult-aspnet-mvc-reflection/

     


    Peter Kellner http://peterkellner.net Microsoft MVP • ASPInsider
    Saturday, May 15, 2010 4:20 AM