Using JSON in MVC Controller

I've encountered numerous discussions on SO about this particular issue, but the proposed solutions have not worked for me. I am currently feeling confused and wondering if I am overlooking something?

Just to clarify, I am a beginner when it comes to .js.

My approach involves retrieving values from dynamically created form elements using the following JS code and attempting to post them:

UPDATE 12:21: I have implemented a script that is supposed to parse each element from the form into a custom array resembling JSON. However, I still encounter null references. Any suggestions on how to resolve this?

 var getValues = function (myForm) {
        var array = [];
    var parser;

    $("formElement").each( function (i, elem) {

            parser.empty()
            parser = {
                Id: $(elem,"#Id ").val(),
                someOption: $(elem, "#someOption ").val(),
                someText: $(elem, "#someText ").val(),
                someNumber: $(elem, "#someNumber  ").val()
            }
            array.push(parser);

        });

    console.log(array);


    $.ajax({
        type: "POST",
        url: 'angus',
        traditional: true,
        data:  {json: array },
        success: function (data) {
            $("#getData").empty();
            $("#getData").append(array);
        }
    });            
    };

In the log, I see: (objects of index like i,i+1,i+2,i+3 match the viewmodels - is it right? and I have mixed feelings about those proto and functions - what is it?) https://i.sstatic.net/Xc908.png

However, in my controller action, I encounter a null exception:

 [HttpPost]
        public ActionResult angus(IEnumerable<TrashViewModel> json)
        {

            return View(json.ToList());
        }

I have created my own view model:

  [Serializable]
public class TrashViewModel
{
    public int Id { get; set; }
    public string someOption { get; set; }
    public string someText { get; set; }
    public string someNumber { get; set; }

}

The names of HTML attributes in my form matching those of the viewmodel class.

UPDATE: html:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="formExample" ng-controller="ExampleController">

    <button class="btn btn-primary" ng-controller="addRow" ng-click="addLine()">Add Button</button>

    <form novalidate class="simple-form">
        <div class="here">
            <div class="formElement row">

                  <input type="hidden" name="Id" value="1"/>
                <div class="col-md-2">
                    <select name="someOption" class="optns form-group col-md-12" ng-model="user.class">
                        <option selected value="1"> Type... </option>
                        <option value="test">2</option>
                        <option value="2">test</option>
                        <option value="2">2</option>
                        <option value="3">3</option>
                        @*options will be added here*@;
                    </select>
                </div>
                <div class="col-md-1">
                    <input name="someNumber" class="form-group col-md-12" type="number" ng-model="user.number" value="" text="Amount..." /><br />
                </div>
                <div class="col-md-9">
                    <input name="someText" class="form-group col-md-12" type="text" ng-model="user.text" value="" text="Remarks..." /><br />
                </div>
            </div>
        </div>
        <input type="button" value="Reset" />
        <input type="submit" value="Save" />
    </form>
</div>

Appended html:

 var strVar = "";
            strVar += "<div class=\"formElement row\">";
            strVar += "                  <input type=\"hidden\" name=\"Id\" value=\" "+ $scope.counter +"\"\/>";
            strVar += "                <div class=\"col-md-2\">";
            strVar += "                    <select name=\"someOption\" class=\"optns form-group col-md-12\" ng-model=\"user.class\">";
            strVar += "                        <option selected value=\"1\"> Type... <\/option>";
            strVar += "                        <option value=\"test\">2<\/option>";
            strVar += "                        <option value=\"2\">test<\/option>";
            strVar += "                        <option value=\"2\">2<\/option>";
            strVar += "                        <option value=\"3\">3<\/option>";
            strVar += "                        @*options will be added here*@";
            strVar += "                    <\/select>";
            strVar += "                <\/div>";
            strVar += "                <div class=\"col-md-1\">";
            strVar += "                    <input name=\"someNumber\" class=\"form-group col-md-12\" type=\"number\" ng-model=\"user.number\" value=\"\" text=\"Amount...\" \/><br \/>";
            strVar += "                <\/div>";
            strVar += "                <div class=\"col-md-9\">";
            strVar += "                    <input name=\"someText\" class=\"form-group col-md-12\" type=\"text\" ng-model=\"user.text\" value=\"\" text=\"Remarks...\" \/><br \/>";
            strVar += "                <\/div>";
            strVar += "            <\/div>";

I continue to face null exceptions, as other posts suggest, due to the viewmodel class not aligning with the serialized objects. Uncertain on next steps.

Thank you!

Answer №1

If you want to send your array using a POST request, make sure to convert the data into a string and specify the contentType option in your Ajax code like this:

$.ajax({
    type: 'POST',
    url: '@Url.Action("angus")', // Avoid hard coding URLs
    contentType: "application/json; charset=utf-8",
    data: JSON.stringify({ model: array }), 
    success: function (data) {

Also, update your controller method to accept the array properly:

[HttpPost]
public ActionResult angus(IEnumerable<TrashViewModel> model)

Answer №2

Consider trying a different approach by:

 var parsed = $(myForm).serializeArray();

and replacing it with:

 var parameters = {
            Id : $("#Id").val(),
            someOption : $("#someOption").val(),
            someText : $("#someText").val(),
             someNumber  : $("#someNumber").val()
       };

Next, submit the data using:

JSON.stringify(parameters)

Answer №3

When looking at your JavaScript code, there are a few things that stand out to me:

  1. You are using .serializeArray() to create an array of objects with name and value properties, which doesn't align with the structure of your TrashViewModel object.
  2. You are adding unnecessary structure by wrapping the serialized object inside a new object with a "json" property.
  3. You are unnecessarily stringifying the object.

All this extra manipulation is not needed because the .ajax() method will format the data correctly for you. You simply have to pass the serialized form as the data parameter.

data: $(myform).serialize()

In the controller, simply set the parameter on the action to be your TrashViewModel object. Keep in mind it's a single object, not an enumerable.

public ActionResult Angus(TrashViewModel form)
{
    // do something
}

If you decide to use .serializeArray(), then you'll need to create a model object with Name and Value properties for the model binder to resolve the parameters correctly.

// JavaScript 
data: $(myform).serializeArray()

// Controller
public class NameValueModel
{
    public string Name { get; set; }
    public string Value { get; set; }
}

public ActionResult Angus(NameValueModel[] form)
{
    // do something
}

Answer №4

Despite not being completely satisfied with the outcome, I am still required to parse a JSON string on the server side. To make it easier for others in the future, I plan on creating a Q&A guide. Special thanks to:

  • @StephenMuecke
  • @Emil
  • @Jeff M

Here is a summary of what I did:

I wrote JavaScript to collect inputs and apply custom styles before making a POST request using AJAX:

        var array = [];
        var parser;

        $(".formElement").each( function (i, elem) {

                //parser.empty()
                parser = {
                    Id: $("#Id", $(this)).val(),
                    someOption: $("#someOption", $(this)).val(),
                    someText: $("#someText", $(this)).val(),
                    someNumber: $("#someNumber", $(this)).val()
                };
                console.log(parser);
                array.push(parser);

            });

        console.log(array);


        $.ajax({
            type: "POST",
            url: 'angus',
            traditional: true,
            data: { json: JSON.stringify(array) },
            success: function (data) {
                $("#getData").empty();
                $("#getData").append(array);
            }
        });

When looking at the controller code:

While the logic may seem unnecessary in this context, the key takeaway was passing the string type as a parameter; this ensured successful integration with the complex type viewmodel.

       [HttpPost]
        public ActionResult angus(string json)
        {

            var check = json.ToString() == null;

            return RedirectToAction("ErrorAction");
        }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to send a query in a jQuery AJAX call?

I am a beginner in working with AJAX requests and server programming. This project is part of my school assignment. I need to include the SID that was generated as a parameter for this request. Additionally, I am trying to pass in an object of colors, a st ...

Why is it necessary to click twice with AjaxUpload?

Utilizing AjaxUpload.2.0.min.js, the following code facilitates file uploads to the server. An issue arises where multiple clicks on the “Add File” button are required for the OS window (for selecting the file to upload) to appear, rather than just on ...

Turn the image inside the div with the nth-child selector into a clickable link

I'm currently facing a challenge on my Squarespace website where I need to add individual links to various images using jQuery. The issue is that these images do not have a shared class, and unfortunately, I am limited to adding custom CSS or JavaScri ...

Is there Polyfill Compatibility for Custom Elements in Angular 9?

When it comes to polyfilling support for custom elements created with Angular, there are various recommendations available. This demo demonstrates that adding the following polyfill in polyfills.ts works: import '@webcomponents/webcomponentsjs/custo ...

Adding an image to a Select Option label in React: A simple guide

As a newcomer to React, I am experimenting with creating a drop-down menu that includes images in the labels. My approach involves using a function to gather values from a map and construct an id: label pair to display as options in the drop-down. Both the ...

Vue 3 and Bootstrap 5 seem to be struggling with finding the properties of an undefined 'backdrop'

I am facing an issue with Vue3 (Vite) and Bootstrap 5 while trying to create a modal that can be called by code. The problem arises when I attempt to open the modal from its parent component. Bootstrap has been properly installed and included in my projec ...

"Exploring the process of assigning input data to a different variable within a Vue component

Reviewing the code snippet I currently have: <template> <div> <input v-model.number="money"> <p>{{ money }}</p> </div> </template> <script> name: 'MyComponent', data () { ...

Iterate through a jQuery function to retrieve values from checkboxes starting from the 4th one that has been clicked

I am currently using a loop in a form to calculate the total price of a product based on user selections. However, I have encountered a challenging task where certain checkbox groups have specific rules. For instance, group A should only contribute to the ...

Is there a way to update my Google Maps .html file on my android phone to pan to my current location?

An objective is to create a local .html file on an android device that can be accessed through a standard web browser, allowing users to pan to their current location on Google Maps. Presently, the panning feature works on the Mi browser on android devices ...

Continuously send HTTP requests to the page until receiving a status code of 200, then proceed to redirect to the same page

I am new to JavaScript and seeking advice on how to tackle this task. I have attempted the following approach, but it is not functioning correctly: while (status !== 200) { checkPage(); } function checkPage() { var xhr = new XMLHttpReque ...

Looking to transfer a cell value to different cells within an HTML table

Currently, I am utilizing a basic HTML code to duplicate the value from the first cell to all other cells. You can take a look at how the HTML table appears here. In addition, I am attempting to automatically fill in the remaining dates once input is provi ...

I am encountering an issue where the useState hook is returning an undefined value on separate components, even after

When setting up a login context, I wrap all my routes with the context provider and pass the initial value using useState: <userContext.Provider value={{loggedUser, setLoggedUser}}> In LogInMenu.jsx, which is responsible for setting the loggedUser ( ...

Using Javascript to delete a cookie that was created by an AJAX response

Within my Webapp (which is currently running at localhost/myApp/), I am utilizing an ajax call as shown below: $.ajax({ type: "GET", url: "http://localhost:8080/my.module/Login/login?user=abc&password=123", xhrFields: { withCredent ...

Looking for a way to implement a vertical autoscroll <ul> list that responds to mouse movement using JavaScript and jQuery

Could you assist me in enabling the list items to be moved using mouse movement? When the user moves the mouse cursor vertically upward over the list, the list should scroll downward. If the user moves the mouse cursor downward over the list, the list shou ...

How can we parse the returned 'data' as HTML in JavaScript/jQuery to select more elements?

After receiving data from a webservice, it turns out that the data is just raw HTML without any XML headers or tags around it, but simply a piece of HTML code. <div class="Workorders"> <div id="woo_9142" class="Workorder"> <span ...

Implement the insertion of JSON items in real-time by leveraging the power of Angular JS and

I'm facing a challenge trying to insert JSON items into a dynamic list: The structure of my JSON file is as follows: [ { "id":"34", "City":"New York", "Country":"USA" }, { "id":"22", "City":"Las vegas", "Country":"USA" }, { "id":"44", "City":"Paris" ...

Looking to find a specific term within a JSON object that contains various fields

{ "TaskType": "kkkk", "Status": "SUCCESS", "jobID": "18056", "DownloadFilePath": "https://abcd", "accountId": "1234", "customerId": &q ...

Transmit HTML form information through a POST request to an ASP.NET web service

Having an HTML page with a contact form is great, but I'm facing the challenge of sending the data using AJAX. I attempted to send the data to a webservice without converting the structure to JSON format, but unfortunately, I did not succeed. Is ther ...

Tips for submitting a form using yui3

While utilizing YUI3's io-form module to submit a form, I encountered an issue where the server received null field values. Any insights or assistance would be greatly appreciated. <form name='testajax' id="testajax1"> <input typ ...

Prevent any pop-up windows from appearing when a specific link is clicked

On my website, I have implemented popup advertising where ads open when clicked inside the body. However, I am looking to disable popups when a link with the class donot is clicked. Currently, when the donot link is clicked, a popup opens and the link doe ...