Goldentp
Goldentp

Reputation: 197

Return a second variable in a JSON array

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!

Upvotes: 1

Views: 2133

Answers (2)

GameScripting
GameScripting

Reputation: 17012

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();
}

Upvotes: 3

AndrewR
AndrewR

Reputation: 6758

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);

Upvotes: 1

Related Questions