-3

Can anyone help me with the following. I'm trying to POST JSON data to a controller, but the controller never populates the variable with the data.

This is the controller and always displays null.

This is the controller.

public ActionResult SyncMail(List<MailSyncDTO> emailLst)
{
    return null;
}

The view looks like this;

foreach (var item in Model)
    <td><input name="emailLst.emailSource" id="emailSource" type="text" value="@item.emailSource" /></td>
    <td><input name="emailLst.emailDestination" id="emailDestination" type="text" value="@item.emailDestination" /></td>
    <td><input name="emailLst.SyncMail" id="SyncMail" type="checkbox" /></td>
    <td><input name="emailLst.ID" id="ID" type="text" value="@item.ID" hidden /></td>
</tr>
}

    function Update() {
        var emailLst = [];
        $('#tblEmails tr').each(function () {
            var obj = new Object();
            var emailSource = $(this).find("input").each(function () {
                if (this.id == 'emailSource' && this.value != '') {
                    obj.emailSource = this.value;
                }
                else if (this.id == 'emailDestination' && this.value != '') {
                    obj.emailDestination = this.value;
                }
                else if (this.id == 'SyncMail' && this.value != '') {
                    obj.SyncMail = this.value;
                }
                else if (this.id == 'ID' && this.value != '') {
                    obj.ID = this.value;
                }
            })
            emailLst.push(obj);
        });

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

I can see in Fiddler that the data is being sent.

POST http://localhost:53545/MailSyncDBs/SyncMail HTTP/1.1
Content-Type: application/json; charset=utf-8
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
Referer: http://localhost:53545/MailSyncDBs/Index
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
Content-Length: 336
Host: localhost:53545
Connection: Keep-Alive
Pragma: no-cache
{"emailLst":[{},{"emailSource":"source@mail.co.uk","emailDestination":"destination@mail.co.uk","SyncMail":"on","ID":"1"},{"emailSource":"source1@mail.co.uk","emailDestination":"destination1@mail.co.uk","SyncMail":"on","ID":"2"},{"emailSource":"source2@mail.co.uk","emailDestination":"destination2@mail.co.uk","SyncMail":"on","ID":"3"}]}

This is the DTO that is referenced;

public class MailSyncDTO
{
    public string ID { get; set; }
    public string emailSource { get; set; }
    public string emailDestination { get; set; }
    public string SyncMail { get; set; }
}
Antoine Thiry
  • 2,362
  • 4
  • 28
  • 42
Nathan Linus
  • 53
  • 1
  • 5
  • 1
    [I downvoted because](http://idownvotedbecau.se/imageofcode) (and you sending a collection of objects, not a collection of strings) –  Mar 21 '18 at 22:01

1 Answers1

0

Your controller wants to receive a List<string> but you are not sending him one. In the way you made your controller, the Json you are sending should looks something like this :

["source@co.uk","source@co.uk","source@co.uk"]

You can create a DTO in your C# project who will reflect exactly your Json and will be auto-mapped in your controller.

I've tested it with this javascript method :

function testIt() {
    var emailLst = [];

    // Replace bellow part with yours
    var obj = new Object();
    obj.EmailDestination = "dest@co.uk";
    obj.Source = "source@Context.uk";
    obj.SyncMail = "on";
    obj.Id = "1";
    emailLst.push(obj);
    // Replace above part with yours


    // Adding this before sending will make sure that you are not sending any empty objects.
    emailLst.forEach(function(item, i) {         
        if ($.isEmptyObject(item)) {
            emailLst.splice(i, 1);
        }
    });

    $.ajax({
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        type: 'POST',
        url: '/MailSyncDBs/SyncMail',
        data: JSON.stringify(emailLst)  // And not JSON.stringify({emailLst : emailLst })
    });
}

Try adding a class like this one :

public class SyncMailDto
{
    public string EmailSource {get; set;}
    public string EmailDestination {get; set;}
    public string SyncMail {get; set;}
    public string Id {get; set;}    
}

And change the signature of your controller method to :

[HttpPost]
public JsonResult SyncMail(List<SyncMailDto> emailLst){

    foreach(var mail in emailLst){
         // Do something with your mail
    }

    return Json("It Works !");
}

If you wanted to use exactly the javascript you wrote you would have to add another DTO class to wrap the list. Because that's what you did with JSON.stringify({EmailLst : EmailLst}).

public class MailListWrapperDto{
    public List<SyncMailDto> EmailLst {get;set;}
}

And the signature of your POST Method :

public JsonResult SyncMail(MailListWrapperDto emailLst)
Antoine Thiry
  • 2,362
  • 4
  • 28
  • 42
  • Thanks Antoine, I’ll try it in the morning. I’m new to Json and MVC, but I thought the json.stringify was converting the data to a string before sending it. Is that not incorrect? – Nathan Linus Mar 21 '18 at 22:54
  • It is not that incorrect, but the data you want to convert is a list of object, not a list of string. And to be exact you don't need to stringify the json if I'm correct. – Antoine Thiry Mar 22 '18 at 05:27
  • I still can't get this to work. I've started a new project because I was making a mess of the other one. I've added a DTO with string properties. The variable is still null. I've updated the original question with the updated DTO and removed the images. – Nathan Linus Mar 22 '18 at 13:18
  • @NathanLinus I've edited my answer with the javascript code and tested it in Visual Studio 2017 and it works ok. The real problem was the way you were sending your Json. – Antoine Thiry Mar 22 '18 at 13:36
  • Please consider marking this as answer if it helped you – Antoine Thiry Mar 22 '18 at 15:09
  • No, it's still not working. It now picks up the first lot of data, but not the other entries. – Nathan Linus Mar 22 '18 at 15:34
  • @NathanLinus I've edited the javascript bit so it removes empty items from the json. (You should try to not copy/paste code in the comment section) – Antoine Thiry Mar 22 '18 at 15:49
  • It's now working. I've added an id to the row that is being looped and change JavaScript to use the id, rather than the general table row. It's now looping through successfully and updating the controller variable. Thanks again Antoine for all your help! (I've removed the code, thanks for the advice) – Nathan Linus Mar 22 '18 at 16:29