1

I am trying to pass a second variable out of a JSON array that is of type int. So far I have only been able to pass the SP_NAME (which is a string) variable out but now I need the SP_ID to be passed out of the controller as well so the jQuery knows where to place the information.

Below is the controller code. There are two lines where I think the trouble is coming from and I have added <------ arrows to show you guys.

[Authorize]
public virtual ActionResult getAjaxSPs(string MP = null)
{

    if (MP != null)
    {
        var SPList = from x in sp_index select x;


        var MPData = from y in mp_index
                     where y.MP_NAME == MP
                     select y;

        SPList = SPList.Where(x => x.MP_ID == MPData.FirstOrDefault().MP_ID);

        var SPRow = SPList.Select(x => new { x.SP_NAME, x.SP_ID }).Distinct().ToArray();  // <------- SPRow returns two variable SP_NAME and SP_ID (ex. Program1, 30) 

        float[] SPContent = new float[12];

        Dictionary<string, float[]> SPMonthRow = new Dictionary<string, float[]>();

        foreach (var item in SPRow)
        {

            SPContent = new float[12];

            var SPMonthList = from x in Full_Year_Numbers
                              where x.PROJECT_NAME == item.SP_NAME
                              group x by new { x.ACCOUNTING_PERIOD, x.PROJECT_NAME, x.AMOUNT } into spgroup
                              select new { accounting_period = spgroup.Key.ACCOUNTING_PERIOD, amount = spgroup.Sum(x => x.AMOUNT) };

            foreach (var mulan in SPMonthList)
            {
                int acounting_period = int.Parse(mulan.accounting_period) - 1;
                SPContent[acounting_period] = (float)mulan.amount / 1000000;

            }

            SPMonthRow[item.SP_NAME] = SPContent;
        }

        return Json(SPMonthRow, JsonRequestBehavior.AllowGet); //<--------- This is where I need to return two variables so I can use them both in the Jquery

    }
    return View();
}

So in the SPRow line I am getting the key and the values that I need which are (program1, 30). I need to have access to the SP_ID in the JSON return so I can use it in my jQuery like this.

<div class = "sp-label" title = "' + SP + '" sub_program_id="' + SP.SP_ID + '" onclick="sp_click(this)">' + SP + '</div>'

I thought that I could just add item.SP_ID to SPMonthRow like this

SPMonthRow[item.SP_NAME, item.SP_ID] = SPContent;

But, when I tried to build again I received this error

no overload for method 'this' takes 2 arguments

This error leads me to believe that I defined the dictionary incorrectly, am I correct in thinking this or am I off track? Is there another way to get the SP_ID into the JSON array that is being used in the jQuery? I am honestly open to any and all suggestions to get SP_ID out of that controller. I have been googling for a while now with no idea on how to fix an issue like mine. Thanks for your help and please let me know if you need any other code or information to help with diagnosis of the issue.

Update 1

foreach (var item in SPRow)
                {

                    SPContent = new float[12];

                    var SPMonthList = from x in act.WPD_Full_Year_Actuals
                                      where x.PROJECT_NAME == item.SP_NAME
                                      group x by new { x.ACCOUNTING_PERIOD, x.PROJECT_NAME, x.AMOUNT } into spgroup
                                      select new { accounting_period = spgroup.Key.ACCOUNTING_PERIOD, amount = spgroup.Sum(x => x.AMOUNT) };

                    foreach (var mulan in SPMonthList)
                    {
                        int accounting_period = int.Parse(mulan.accounting_period) - 1;
                        SPContent[accounting_period] = (float)mulan.amount / 1000000;

                    }

                    dynamic result = new
                        {
                            Name = item.SP_NAME,
                            Id = item.SP_ID
                        };

                    SPMonthRow[result] = SPContent;
                }

                return Json(SPMonthRow, JsonRequestBehavior.AllowGet);

            }
            return View();
        }

Update 2

Here is the schema of the tables used in this function

public partial class sp_catalog
    {
        public int SP_ID { get; set; } //primary key
        public Nullable<int> MP_ID { get; set; }
        public Nullable<int> IA_ID { get; set; }
        public string SP_NAME { get; set; }
    }


public partial class mp_catalog
    {
        public int MP_ID { get; set; } //primary key
        public Nullable<int> IA_ID { get; set; }
        public string MP_NAME { get; set; }
    }

public partial class Full_Year_Actuals

{
public string ACCOUNTING_PERIOD { get; set; }
public Nullable<decimal> AMOUNT { get; set; }
public string PROJECT_NAME { get; set; }
public int ID_actuals { get; set; }

}

Update 3

I have tried using the dynamic result class but that does not work for me since I cannot use the code GameScripting provided me with. The reason I cannot use it is because I need to work with the SQL DB to provide me with the data. I cannot hard code any data as it is constantly changing.

All I want is to be able to return SP_NAME, SP_ID and the amounts in SPContent through JSON. The reason for this is that in my jQuery I use SP_NAME to output the name of the Sub-Program (ex. "subProgram1"). I use SP_ID to let the jQuery know which program to put the sub-progrm under (ex. if SP_ID = 1 the sub-program would be under program1). The amounts that are contained within SPContent are monthly totals that are entered in the foreach loop.

(program1 Jan Feb Mar

  subProgram1 $100 $200 $300 etc...)`

What this all means is I cannot lose this line SPMonthRow[item.SP_NAME] = SPContent; unless I can output SPContent amount data another way. I am open to all solutions as long as I can keep the data flowing out of the function in JSON so the jQuery can display what I need it to. Sorry for the essay I just want to make sure anyone who wants to help me has the information required to do so. Please feel free to ask any questions or make any request for code as I check the status of my questions often. Thank you for your help!

Goldentp
  • 187
  • 1
  • 7
  • 28
  • The answers below are two ways you can solve your issue. Your original code creates JSON using two pieces of data. One data is the NAME (the Dictionary Key), and the other is an array of float called CONTENT (the Dictionary Value). In order to return a third data, you need to create a new class object or a dynamic object. The Dictionary can only hold two pieces of your data, so you can't use that anymore. Since you are passing an additional piece of data, whatever consumes your JSON will also need to be updated for the new format. Hopefully this helps clarify what you need to do. – AndrewR Sep 11 '12 at 17:55

2 Answers2

3

When using .NET 4.0+ you can use a dynamic type to merge those two values into a new object and return that just like

dynamic result = new
{
    Name = item.SP_NAME,
    Id = item.SP_ID
};
return Json(result, JsonRequestBehavior.AllowGet); 

UPDATE:

I really don't understand what your code is about something about SPs and MPs, which seem to have a releationship with each other. So I can't provide any help with your code, until you'll explain what you are trying to archive, what there querys represent etc. I'll try to provide some generic information about array' and dictionarys.

Let's firstly have a look at what is avalible


JSON

{
   "Key1":5,
   "Key2":10,
   "Key3":155
}

C# (you could also use dictionary initialisation syntax)

Dictionary<string, int> dictionary = new Dictionary<string, int>();

dictionary.Add("Key1", 5);
dictionary.Add("Key2", 10);
dictionary.Add("Key3", 155);

This structure is called a dictonary, which is a simple key-value store. You can say: "Here I've got some data, please save it as program1". Later you can go out and say: "can you please give me the data use saved as program1".

JSON

[
   5,
   15,
   23,
   78,
   155,
   4,
   85
]

C# (again initialisation syntax is avalible)

int[] array = new int[6];
array[0] = 5;
array[1] = 15;
array[2] = 23;
array[3] = 78;
array[4] = 155;
array[5] = 4;
array[6] = 85;

This is an array which is just an accumulation of values, which get automatically a unique number in the accumulation (this is called index). These unique number start at 0, not at 1.

What you actually have is a dictionary with a string key and an array of numbers as the actual data.

JSON

{
   "program1":[
      101,
      34,
      67,
      876
   ]
}

C#

Dictionary<string, int[]> dictionary = new Dictionary<string, int[]>();

int[] values = new int[4];
values[0] = 101;
values[1] = 34;
values[2] = 67;
values[3] = 876;

dictionary.Add("program1", values);

Let's have a look at want you want


You want something like

{
   "program1", "30":[
      101,
      34,
      67,
      876,
      44
      7
   ]
}

So, what it that? A dictionary? An array? how would you access the program1 element? Just that name? But what's the "30" then? As you see, there's no answer, such a thing doen't exist.

My solution

I think you want the following structure:

JSON

{
   "program1":{
      "30":[
         34,
         67,
         876,
         44,
         36,
         6
      ]
   }
}

The C# code to get such a struct would be something like

dynamic data = new
{
    program1 = new Dictionary<string, int[]>
    {
        {"30",  new int[]{34,67,876,44,36,6}}
    }
};

Now it's you turn to figure out what you really want and how to make your code work. Happy coding :)


UPDATE2

If you just want working code, without understanding what happens actually, try this one:

[Authorize]
public virtual ActionResult getAjaxSPs(string MP = null)
{

    if (MP != null)
    {
        var SPList = from x in sp_index select x;


        var MPData = from y in mp_index
                        where y.MP_NAME == MP
                        select y;

        SPList = SPList.Where(x => x.MP_ID == MPData.FirstOrDefault().MP_ID);

        var SPRow = SPList.Select(x => new { x.SP_NAME, x.SP_ID }).Distinct().ToArray();  // <------- SPRow returns two variable SP_NAME and SP_ID (ex. Program1, 30) 

        float[] SPContent = new float[12];

        List<dynamic> result = new List<dynamic>();

        foreach (var item in SPRow)
        {

            var SPMonthList = from x in Full_Year_Numbers
                                where x.PROJECT_NAME == item.SP_NAME
                                group x by new { x.ACCOUNTING_PERIOD, x.PROJECT_NAME, x.AMOUNT } into spgroup
                                select new { accounting_period = spgroup.Key.ACCOUNTING_PERIOD, amount = spgroup.Sum(x => x.AMOUNT) };

            foreach (var mulan in SPMonthList)
            {
                int acounting_period = int.Parse(mulan.accounting_period) - 1;
                SPContent[acounting_period] = (float)mulan.amount / 1000000;

            }

            result.Add(
                new {
                    Name = item.SP_NAME,
                    Id = item.SP_ID,
                    Content = SPContent
                });
        }

        return Json(result, JsonRequestBehavior.AllowGet);
    }
    return View();
}
Community
  • 1
  • 1
GameScripting
  • 16,092
  • 13
  • 59
  • 98
  • I tried this and it seems like it should work. It kind of did but not completely. When I ran a trace it retrieved the data and put program1 into name and 30 in Id. (I have added an update to show what the code looks like now in the question above.) After the code ran the last line `SPMonthRow[result] = SPContent;` it threw an error RuntimeBinderException was unhandled by user code `"The best overloaded method match for 'System.Collections.Generic.Dictionary.this[string]' has some invalid arguments"` -----Any Ideas?? – Goldentp Sep 10 '12 at 20:19
  • Did I add the code in the wrong place or is it how I set my dictionary up? – Goldentp Sep 10 '12 at 20:22
  • 2
    Drop this row: `SPMonthRow[result] = SPContent;` and what you want to return is `return Json(result, JsonRequestBehavior.AllowGet); ` – AndrewR Sep 10 '12 at 21:49
  • @AndrewR Two reasons I cannot drop the row `SPMonthRow[result] = SPContent;` First I need to add the result to the second array `SPMonthRow` Second when I tried to add the code you suggested I got a red squiggly under result that says `The name 'result' does not exist in the current context.` – Goldentp Sep 11 '12 at 14:01
  • @Goldentp Come on! Show some effort instead of simply saying "I can't do that"! `First I need to add the result to the second array` For what reason? Provide more details! – GameScripting Sep 11 '12 at 14:18
  • @GameScripting Sorry I didn't mean to be vague The reason I cannot add the result without SPMonthRow is because SPMonthRow contains the numbers for each month in the array so the response would look like {"program1":[101,34,67,876,44,36,6,88,233,555,56,7]}, I need the response to look like {"program1", "30":[101,34,67,876,44,36,6,88,233,555,56,7]} I hope that this makes sense. I honestly was trying to provide you with as many details as possible without being verbose, I am sorry if you need any more information I would be happy to provide anything you require. – Goldentp Sep 11 '12 at 14:31
  • +1 for the update with the extended information, explanations, and code. – AndrewR Sep 11 '12 at 17:46
1

You can create a new object to use for your JSON result.

Something like:

[Serializable]
public class SPData{
    string SP_NAME{get;set;}
    float SP_CONTENT{get;set;}
    int SP_ID{get;set;}
}

Then when you use it, make a List<> of SPData and add a new one each loop.

List<SPData> SP_DATA = new List<SPData>();

foreach (var item in SPRow)
{
    // ...

    SP_DATA.Add(new SPData{SP_NAME=item.SP_NAME, SP_CONTENT=SPContent, SP_ID=item.SP_ID});
}

return Json(SP_DATA, JsonRequestBehavior.AllowGet);
AndrewR
  • 6,668
  • 1
  • 24
  • 38
  • Does it matter that SP_CONTENT is only used to store array values for another array. It is pretty much used to put the correct amounts into the correct months in the display. Also I am using MVC 3 do I need to put the getters and setters in the model or can I declare those in the same controller where I am using them? – Goldentp Sep 10 '12 at 20:29
  • 1
    If you need the SP_CONTENT field included in the JSON data, then you may need to change it to a `float[]` instead. I didn't check close enough to see how that data was defined. The SPData class would not be part of your model for MVC. It is separate. – AndrewR Sep 10 '12 at 21:05
  • I am confused about how to keep the current data intact while adding the field that I need SP_ID to the JSON. I need the new code to work with the existing code. Thank you for your help in both answers, upvote for you sir! – Goldentp Sep 11 '12 at 14:06
  • Please see my comment above on the question. The key to solving this is not adding an additional data field to the Dictionary (you can't) but creating a new object that holds your data, either defined as a class like my answer, or using dynamic as @GameScripting has suggested. – AndrewR Sep 11 '12 at 17:58