4

I'm working on an ASP.NET MVC 4 website and I've got some troubles with a functionality. I explain, I've to select entities displayed in a table with their linked checkbox :

Screenshot of my table where each row has a checkbox with the same Id as the entity

Console showing updates in the array

Inside my script I have been abled to store each checked Id's checkbox in an array and remove those if the checkbox is unchecked. But I can't pass the array to my controller's function to delete each selected entity in the database. I used $.ajax() from jquery to send through a POST request the array (as JSON) but I always get 500 error :

  • JSON primitive invalid
  • Null reference

Here's my function in my script (I don't know if my array's format is valid) :

    var sendDocsToDelete = function (docsArray) {
        $.ajax({
            type: 'POST',
            url: 'Main/DeleteDocuments',
            data: JSON.stringify(docsArray),
            contentType: 'application/json; charset=utf-8',
            datatype: 'json',
            success: function (result) {
                alert('Success ' + result.d);
            },
            error: function (result) {
                alert('Fail ' + result.d);
            }
        });
    }

Then, the POST call the following function in my controller :

    [Authorize]
    [WebMethod]
    public void DeleteDocuments(string docsToDelete)
    {
        int id; 
        string[] arrayDocs = JsonConvert.DeserializeObject<string[]>(docsToDelete);

        foreach (string docId in arrayDocs)
        {
            int.TryParse(docId, out id);
            dal.DeleteDocument(id); // dal = DataAccessLayer is the class which interacts with the database by executing queries (select, delete, update...)
        }
    }

Update 2

    [Authorize]
    public ActionResult DeleteDocuments(int[] docsToDelete)
    {
        try{
               foreach (string docId in arrayDocs)
               {
                       int.TryParse(docId, out id);
                       dal.DeleteDocument(id); // dal = DataAccessLayer is the class which interacts with the database by executing queries (select, delete, update...)
               }
               return Json("Success");
        } 
        catch 
        {
               return Json("Error");
        }
    }


    var sendDocsToDelete = function (docsArray) {
        $.ajax({
            type: 'POST',
            url: 'Main/DeleteDocuments',
            data: docsArray,
            contentType: 'application/json; charset=utf-8',
            datatype: 'json',
            success: function (result) {
                alert('Success ' + result.d);
            },
            error: function (result) {
                alert('Fail ' + result.d);
            }
        });
    }

Any ideas about this issue ? I hoped I was clear enough. Do not hesitate if you need more details.

6
  • 2
    why using a webMethod in MVC ? you can just use ActionResult Commented May 19, 2016 at 13:55
  • 1
    You don't need to stringify the data yourself, just pass the array as it is. And you don't need to deserialize it yourself either, just accept string[] docsToDelete and let the modelbinder handle that for you. Commented May 19, 2016 at 13:58
  • @Reddy I thought it was compulsory by this way because I wasn't expecting a view but an asynchronous update of the actual view. Commented May 19, 2016 at 14:08
  • @DavidHedlund I tried but it still fails to recognize my parameter... Commented May 19, 2016 at 14:09
  • @Loïc you can pass back string too from the ActionResult.. Commented May 19, 2016 at 14:11

4 Answers 4

5

If you are passing an integer array properly from $.ajax (i.e. your docsArray should be having value like [15,18,25,30,42,49]) then you should try :

[Authorize]
public ActionResult DeleteDocuments(int[] docsArray)
{
    //int id; 
    //string[] arrayDocs = JsonConvert.DeserializeObject<string[]>(docsToDelete);
  try {
    foreach (int docId in docsArray)
    {
        //int.TryParse(docId, out id);
        dal.DeleteDocument(docId); // dal = DataAccessLayer is the class which interacts with the database by executing queries (select, delete, update...)
    }
    return "Success ";
  }
  catch {
        return "Error";
  }
}

Update :

Your javascript code should be :

var sendDocsToDelete = function (docsArray) {
    $.ajax({
        type: 'POST',
        url: 'Main/DeleteDocuments',
        data: JSON.stringify(docsArray),
        contentType: 'application/json; charset=utf-8',
        datatype: 'json',
        success: function (result) {
            alert('Success ');
        },
        error: function (result) {
            alert('Fail ');
        }
    });
}
Sign up to request clarification or add additional context in comments.

5 Comments

It have to parse it because my Ids are "checkbox123"
"checkbox123" can not be parse in int, you have to pass integer ids like 123 only.. you can see this : stackoverflow.com/questions/2099164/…
I doubt that AJAX will even hit this method in the first place. Its not a ActionResult
Thanks @Reddy, added ActionResult
@Sachin @Reddy So, I change Ids to be integer (in my view and when I push values in array). But I get again the exception : System.ArgumentException - Primitive JSON invalid : undefined
0

Maybe the datatype in the JSON array is not a string? (This could happen if you have an array in the form of [45,64,34,6], or a mixed one like [345,"wef4"]).

To make sure something is a string in Javascript you can do this: var string = "".concat(otherVar);

1 Comment

Each element in my array are Id defined in my view such as "checkbox123" and in the console I print each value.
0

Try changing your ajax data to something like this..

 data : JSON.stringify({'docsToDelete':docsArray}),

Comments

0

Make these changes to your code.


In Jquery

data: docsArray, no need to stringify the array


In Controller

    [Authorize]                                                //remove [WebMethod]
    public ActionResult DeleteDocuments(string[] docsToDelete) //Add ActionResult, Change parameter to accept array
    {
        int id; 
        string[] arrayDocs = docsToDelete;     //no need of deserilization

        foreach (string docId in arrayDocs)
        {
            int.TryParse(docId, out id);
            dal.DeleteDocument(id); // dal = DataAccessLayer is the class which interacts with the database by executing queries (select, delete, update...)
        }

       return Json(id);    //return id back to ajax call...
    }

3 Comments

Am I maybe missing something but VS says that the ActionResult can't be an integer... Cast not working either.
@Loïc my bad it should be return Json(id);
Ok it makes sense, i'll try