简体   繁体   中英

Reading JSON objects/arrays within a C# Controller

Firstly, I apologise in advance for any incorrect terminology! I've gone snow blind reading so many blog posts and articles on how I might do this and have come to an impasse.

I've been successfully passing parameters via AJAX to an MVC action in a controller, which returns the SQL datatable in JSON format for me to consume in my page. An example set of parameters I send looks like this;

var parameters = {
    pSQL: "SELECT * FROM v_MyTable",
    pSQLServer: "SERVER01",
};

My Client Side Script looks like this;

$.ajax({
    type: 'POST',
    url: '/ControllerName/GiveMeJSON',
    data: JSON.stringify(parameters),
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    ...
});

My Controller Action simply works like this;

    public string GiveMeJSON(string pSQL, string pSQLServer)
    {
        var SQL = pSQL
        var SQLSERVER = pSQLServer

        // do stuff and return JSON
    }

This has been working great for me. I send JSON request data as POST and receive JSON data in return. Brilliant.

Now, I'd like to extend the functionality of my action so that I can pass it an additional set of variables as an array, something like this;

var parameters = {
    pSQL: "SELECT * FROM v_MyTable",
    pSQLServer: "SERVER01",
    pMoreParams: {
        pParameter1: "ABC",
        pParameter2: "XYZ",
    }
};

...where the parameter names in MoreParams could be called anything, with any type of value. That's important, as I think that rules out using models?

This results in the POST request BODY looking like this Valid JSON;

{"pSQL":"SELECT * FROM v_MyTable","pSQLSERVER":"SERVER01","pMoreParams":{"pParameter1":"ABC","pParameter2":"XYZ"}}

So the data I need is clearly going to the server, but yet I am really struggling with enumerating/accessing those additional items in the pMoreParams array. I seem to be getting close, I've played around with using...

public string GiveMeJSON(string pSQL, string pSQLServer, List<string> pMoreParams)

...and I've had a foreach loop in the controller run for however many items are in the pMoreParams list (2, in the above example) but just can't seem to work out how to access/read those values in that list in the controller action.

I'm at a loss now as to how to loop through and read the extra data I am sending. I sense I'm close, with using the List<string> or IEnumerable - but the solution evades me.

I have had more success getting the controller reading those extra parameters when I send them as a simple valid JSON string, like so;

var parameters = {
    pSQL: "SELECT * FROM v_MyTable",
    pSQLServer: "SERVER01",
    pMoreParams: '[{"name": "pParameter1", "value": "ABC" },{"name": "pParameter2", "value": "XYZ"}]'
};

...and using a controller actions which look something like this;

    public class SQLParam
    {
        public string name { get; set; }
        public string value { get; set; }
    }


    if (string.IsNullOrEmpty(pMoreParams) == false)
    {
        var sqlparameters = JsonConvert.DeserializeObject<SQLParam[]>(pMoreParams);
        foreach (var sqlparameter in sqlparameters)
        {
            Debug.WriteLine(sqlparameter.name, sqlparameter.value);
        }
    };

...BUT I then lose the ability to easily read and modify those values in client-side jquery/javascript, and I'd MUCH prefer/desire to keep the way I define the parameters as it is, so that I can easily read and modify the values using a one-liner, something like;

parameters.pMoreParams[0].pParameter1 = "NEW VALUE";

...as I can then simply trigger the AJAX call again and it POSTS with the new parameter values.

Any help and advice is much appreciated, thanks!

When you send in:

"pMoreParams":{"pParameter1":"ABC","pParameter2":"XYZ"}

You are sending in an object called pMoreParams that has two properties.

If you want to get these from the controller, you would need to create a C# object which mirrors the JSON you are sending in.

public class MoreParams
{
    public string pParameter1 {get;set;}
    public string pParameter2 {get;set;}
}

And then update your action method:

public string GiveMeJSON(string pSQL, string pSQLServer, MoreParams pMoreParams)
{
    var param1 = pMoreParams.pParameter1;
    var param2 = pMoreParams.pParameter2;
}

SIDE NOTE

You are sending in SQL for the the server to execute. I know it is convinient, but this is a HUGE security issue that will lead to SQL Injections that will allow an attacker to control your SQL server.

OK, after a good sleep, I think I have come up with a solution which meets my requirements to not have to define all my possible and future parameters in a class and also satisfies some of the SQL injection concerns, having read up on using parameterisation;

Here's the data I JSON.stringify and pass via AJAX to the controller;

var chart01Params = {
pSQLCon: "ConnectionString",
pSQL: "MySQLFile.sql", // accessible only by the server from MapPath
pMoreParams : 
    [
        {
            "name" : "pParameterXYZ",
            "value": "12345ABC"
        },
    ],

};

...which looks like this in POST request body;

{"pSQLCon":"ConnectionString","pSQL":"MySQLFile.sql","pMoreParams":[{"name":"pParameterXYZ","value":"12345ABC"}]}

Here's my class;

public class SQLParam
{
    public string name { get; set; }
    public string value { get; set; }
}

Here's my controller head;

public string GETMYJSON(string pSQLCon, string pSQL, List<SQLParam> pMoreParams)

...before my controller executes the SQL command it will add any parameters and values to the SQL query, which I hope will make it more secure from SQL Injection attack;

foreach (SQLParam parameter in pMoreParams)
{
    cmd.Parameters.Add(parameter.name, SqlDbType.Char);
    cmd.Parameters[parameter.name].Value = parameter.value;
}

And it works great! If I want to send up parameters that a query expects, I can do so without having to include them in a class and I can also, still, use local client-side scripting to take choices/input from the DOM and set parameter values as long as I know the Index in the object of the parameter value I want to change.

Thanks for reading! Before you down-vote someones question, please keep in mind that not everyone is a coding expert who is fully language articulate and has read every book, blog and MSDN article in existence before coming here for help - sometimes all they just came here for what little clarity anyone can offer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM