0

This works fine in MVC4/5, yet for some reason, in MVC Core, I'm receiving NULL at the parameter in the ActionResult. I've also tried it as the "new" JsonResult, same scenario - NULL is what's being received.

It looks good in Fiddler, and JSONLint tells me that it's valid JSON, so I'm baffled as to why I only see NULL and not my data.

Here's the snip for the POST:

function saveClip() {
    console.log("Entered form save function");
    event.preventDefault();
    var formData = getFormData();
    console.log("After getting the form data: ", formData);
    var toSend = JSON.stringify({ clipData: formData });
    console.log("After stringify: ", toSend);

    $.ajax({
        type: "POST",
        url: "Clips/SaveClip",
        data: toSend,
        contentType: "application/json;",
        dataType: "json",
        success: function (response) {
            console.log("Success: ", response);
        },
        error: function (response) {
            console.error("Error: ", response);
        }
    });
};

function getFormData() {
    var publishDate = $("#publishDate").val();
    var category = $("#category").val();
    var headline = $("#headline").val();
    var clipUrl = $("#clipUrl").val();
    var copy = $("#copy").val();
    var notes = $("#notes").val();
    var source = $("#source").val();
    var relatedTo = $("#headlineList").val().length > 0 ? $("#headlineList").val() : null;
    var isNew = $("#isNew").checked ? true : false;

    return {
        PublishDate: publishDate,
        Category: category,
        Headline: headline,
        ClipUrl: clipUrl,
        Copy: copy,
        Notes: notes,
        Source: source,
        RelatedTo: relatedTo,
        IsNew: isNew
    };
};

Here's my ActionResult/JsonResult in the controller:

    [HttpPost]
    public ActionResult SaveClip(string clipData)
    {
        if (null == clipData)
            return Json("No input received.");

        dynamic jsonObject = JsonConvert.DeserializeObject(clipData);

        using (var context = new ClipsSystemContext())
        {
            var clip = new Clip
            {
                PublicationDate = jsonObject.PublicationDate,
                Category = jsonObject.Category,
                Headline = jsonObject.Headline,
                Url = jsonObject.Url,
                Content = jsonObject.Content,
                Notes = jsonObject.Notes,
                Source = jsonObject.Source,
                IsNew = jsonObject.IsNew,
                RelatedTo = jsonObject.RelatedTo,
                AddedBy = Guid.Parse("eed800ab-573f-4453-8fe4-810b8e714edd")
            };

            context.Clip.Add(clip);

            var status = "Clip saved.";
            try
            {
                context.SaveChanges();
            }
            catch (Exception ex)
            {
                status = ex.Message;
            }

            return Json(status);
        }
    }

And, finally, here's the Raw view from Fiddler:

POST http://localhost:1711/Clips/SaveClip HTTP/1.1
Host: localhost:1711
Connection: keep-alive
Content-Length: 265
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost:1711
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
Content-Type: application/json;
Referer: http://localhost:1711/Clips
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: ai_user=PqmJn|2016-09-08T23:11:47.542Z
DNT: 1

{"clipData":{"PublishDate":"10/26/2016","Category":"ba6570f4-1316-4dd5-922e-4739eb9c6c64","Headline":"Ajax Top Story","ClipUrl":"http://www.google.com","Copy":"Ajax top story copy","Notes":"test notes","Source":"Wall Street Journal","RelatedTo":null,"IsNew":false}}

* EDIT - 10/28/2106 * Here's the class defining the ClipModel and the updated ActionResult:

public class ClipModel
{
    public string Headline { get; set; }
    public string Content { get; set; }
    public Guid Category { get; set; }
    public string Source { get; set; }
    public string Url { get; set; }
    public bool IsNew { get; set; }
    public string Notes { get; set; }
    public Guid? RelatedTo { get; set; }
    public DateTime? PublicationDate { get; set; }
}


[HttpPost]
public ActionResult SaveClip(ClipModel clipData)
{
    if (null == clipData)
        return Json("No input received.");
    using (var context = new ClipsSystemContext())
    {
        var clip = new Clip
        {
            PublicationDate = clipData.PublicationDate,
            Category = clipData.Category,
            Headline = clipData.Headline,
            Url = clipData.Url,
            Content = clipData.Content,
            Notes = clipData.Notes,
            Source = clipData.Source,
            IsNew = clipData.IsNew,
            RelatedTo = clipData.RelatedTo,
            AddedBy = Guid.Parse("eed800ab-573f-4453-8fe4-810b8e714edd")
         };
         context.Clip.Add(clip);
         var status = "Clip saved.";
         try
         {
             context.SaveChanges();
         }
         catch (Exception ex)
         {
            status = ex.Message;
         }
         return Json(status);
    }
}
13
  • 1
    Why in the world are you creating and object and then trying to bind it to a string. Delete the contentType: "application/json;", option and use data: formData, and change the method to public ActionResult SaveClip(Clip model). And if you have generated your form controls correctly, then its just data: $('form').serialize(),. 80% of your code is unnecessary. And ALWAYS use url: '@Url.Action("SaveClip", "Clips")', to generate your urls. Commented Oct 27, 2016 at 1:13
  • @StephenMuecke I'm agreed with you, but not always you can use url: @Url.Action("Action","Controller"), for example in .js files, where razor not works. Maximum what you can do - pass the url with parameter. Commented Oct 27, 2016 at 6:00
  • @SeM - In those cases you always use @Url.Action() to generate the url in the main view and pass it to the external file (e.g. as a global variable or a data-* attribute of the element) Commented Oct 27, 2016 at 6:02
  • @StephenMuecke Good to know, thanks. Can you please explain, why is it a bad practice, or may be bad programming style? Commented Oct 27, 2016 at 6:05
  • @SeM, See this answer for some examples. In OP's case, the code may result in a 404 because of the missing leading / (i.e. /Clips/SaveClip) once published Commented Oct 27, 2016 at 6:11

2 Answers 2

0

Try this

 var urlR = '@Url.Action("SaveClip", "Exam")';       
    var formData = getFormData();
    var convertToString = JSON.stringify(formData);

    $.ajax({
        async: false,
        type: "POST",
        url: urlR,
        contentType: "application/json; charset=utf-8",          
        data: JSON.stringify({ clipData: convertToString }),
        cache: false,
        success: function (result) {
            alert("success");

        },
        failure: function (errMsg) {
            //hideprogressbar();
        },
        complete: function () {
            //hideprogressbar();
        }
    });
Sign up to request clarification or add additional context in comments.

1 Comment

this answer did not resolve the issue. Still receiving NULL at the controller even though Fiddler shows all values present.
0

Append the [FromBody] attribute to your Action method:

[HttpPost]
public ActionResult SaveClip([FromBody]ClipModel clipData)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.