locked
How to inspect how default model binder extract data from json and populate server side model RRS feed

  • Question

  • User-454825017 posted

    please tell me a way by which i can see before eyes how model model binder extract data from my json and populate server side model?

    suppose this is my json which i send to action by jquery.

    {
    	"Tick1":"true",
    	"Tick2":"false",
    	"Sections":
    		[
    			{"Section":"Consensus Model","LI":"Operating Earnings Before Income Taxes"},
    			{"Section":"Consensus Model","LI":"Net Income attributable to common, GAAP"},
    			{"Section":"Consensus Model","LI":"Diluted Shares Outstanding"},
    			{"Section":"Consensus Model","LI":"Operating EPS"},
    			{"Section":"Segment Details","LI":"Limited Partnership Income-Retirement"},
    			{"Section":"Segment Details","LI":"Prepayment Fee Income-Retirement"},
    			{"Section":"Segment Details","LI":"Gross Investment Income-Retirement"},
    			{"Section":"Segment Details","LI":"Investment Expenses-Retirement"}
    		]
    }

    Now want to see before eyes how default model binder extract each data and populate my model. this is my model

    [HttpPost]
    public ActionResult Test1(Tuner sdata)
    {
        return Json(new { success = true, responseText = "Your message successfuly sent!" }, JsonRequestBehavior.AllowGet);
    }
    
    public class Tuner
    {
        public string Tick1 { get; set; }
        public string Tick2 { get; set; }
        public List<Sections> Sections { get; set; }
    
    }
    
    public class Sections
    {
        public string Section { get; set; }
        public string LI { get; set; }
    
    }

    please help me with detail information. thanks

    Tuesday, June 23, 2020 10:37 AM

All replies

  • User-474980206 posted

    If you are talking mvc 5 and before, the binder is designed for form post back data, which is a name value collection. So first the json is converted to a dictionary with the json path as the name. Then this collection is bound to the model via reflection

    json to dictionary

    https://github.com/aspnet/AspNetWebStack/blob/master/src/System.Web.Mvc/JsonValueProviderFactory.cs

    dictionary to model  

      https://github.com/aspnet/AspNetWebStack/blob/master/src/System.Web.Mvc/DefaultModelBinder.cs

    Tuesday, June 23, 2020 2:27 PM
  • User-454825017 posted

    Thanks for your link but not getting idea how to debug code and see that each value extraction from json and bind with model. please give me a direction to see json data binding with model which i can debug and see. thanks

    Tuesday, June 23, 2020 4:57 PM
  • User1686398519 posted

    Hi TDP,

    According to your needs, I made an example, you can refer to it.

    • Make sure that the content sent is in JSON format. 
    • Use JSON.stringify to serialize data objects.

    Index

    <button>submit</button>
    @section scripts{
        <script>
            $("button").click(function () {
                var jsonData = {
                    "Tick1": "true",
                    "Tick2": "false",
                    "Sections":
                        [
                            { "Section": "Consensus Model", "LI": "Operating Earnings Before Income Taxes" },
                            { "Section": "Consensus Model", "LI": "Net Income attributable to common, GAAP" },
                            { "Section": "Consensus Model", "LI": "Diluted Shares Outstanding" },
                            { "Section": "Consensus Model", "LI": "Operating EPS" },
                            { "Section": "Segment Details", "LI": "Limited Partnership Income-Retirement" },
                            { "Section": "Segment Details", "LI": "Prepayment Fee Income-Retirement" },
                            { "Section": "Segment Details", "LI": "Gross Investment Income-Retirement" },
                            { "Section": "Segment Details", "LI": "Investment Expenses-Retirement" }
                        ]
                };
                $.ajax({
                    url: '@Url.Action("Test1")',
                    type: "POST",
                    contentType: "application/json; charset=utf-8",
                    data: JSON.stringify(jsonData),
                    success: function (result) {
                        alert(result.success + " "+result.responseText);
                    },
                    error: function (result) {
                        alert("Failed");
                    }
                });
            });
        </script>
    }

    Controller

            public ActionResult Index()
            {
                return View();
            }
            [HttpPost]
            public ActionResult Test1(Tuner sdata)
            {
                return Json(new { success = true, responseText = "Your message successfuly sent!" }, JsonRequestBehavior.AllowGet);
            }

    Here is the result.

     

    Best Regards,

    YihuiSun

    Wednesday, June 24, 2020 6:33 AM
  • User-454825017 posted

    Thanks for the answer.

    i send json this way and then it hit my action and data was deserialize to action parameter 

                $.ajax({
                    type: 'POST',
                    url: '@Url.Action("Test1", "Home")',
                    contentType: 'application/json; charset=utf-8',
                    data: JSON.stringify({ sdata: Tuner }),
                    dataType: 'json',
                    success: function (response) {
                        if (response.success) {
                            alert(response.responseText);
                        } else {
                            // DoSomethingElse()
                            alert(response.responseText);
                        }
                    },
                    error: function (xhr, status, error) {
                        var err = eval("(" + xhr.responseText + ")");
                        alert(err.Message);
                    }
                });
    

    i use this way data: JSON.stringify({ sdata: Tuner }), but you use data: JSON.stringify(jsonData),

    what is the difference between this two approach ?

    in my ajax post i mention sdata which is the name of my action parameter name but you did not use it then how your code working...i need to know the difference between

    these two approaches data: JSON.stringify({ sdata: Tuner }),data: JSON.stringify(jsonData), please put some light here.

    Here i asked for different question that how can i see and debug how model binder extract data from json and populate my model....that answer not given here.

    thanks

    Wednesday, June 24, 2020 6:53 AM
  • User1686398519 posted

    Hi TDP,

    • When using JSON.stringify ({sdata: Tuner}), the parameter name received by your action should be "sdata".Using JSON.stringify(jsonData) only requires that your action receives the same parameter type as jsonData.When you want to pass multiple parameters, you can specify the key and value, such as the following.
    data: JSON.stringify({ sdata: Tuner ,test:"1"})
    public ActionResult Test1(Tuner sdata,string test)
    • TDP

      Here i asked for different question that how can i see and debug how model binder extract data from json and populate my model....that answer not given here.

    For this problem, as long as the format of the Json data you pass is correct, and the key of the json data corresponds to the field name of the model, the model binding can be automatically completed.You can't debug and view it yourself.You can customize the model binding, you can refer to this link about this.

    Best Regards,

    YihuiSun

    Wednesday, June 24, 2020 8:23 AM
  • User-454825017 posted

    I test your code but my action did not hit the break point. i create my json below way. see my full code

    $("#btnSubmit2").click(function () {
                alert('Tuner');
                
    
                var Tuner = {};
                Tuner.Tick1 = 'true';
                Tuner.Tick2 = 'false';
                Tuner.Sections = [];
    
                var Section_LI = {};
                Section_LI.Section='Consensus Model';
                Section_LI.LI = 'Operating Earnings Before Income Taxes';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section='Consensus Model';
                Section_LI.LI = 'Net Income attributable to common, GAAP';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section='Consensus Model';
                Section_LI.LI = 'Diluted Shares Outstanding';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section = 'Test';
                Section_LI.LI = 'Tridip';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section='Consensus Model';
                Section_LI.LI='Operating EPS';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section = 'Segment Details';
                Section_LI.LI = 'Limited Partnership Income-Retirement';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section = 'Segment Details';
                Section_LI.LI = 'Prepayment Fee Income-Retirement';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section = 'Segment Details';
                Section_LI.LI = 'Gross Investment Income-Retirement';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section = 'Segment Details';
                Section_LI.LI = 'Investment Expenses-Retirement';
                Tuner.Sections.push(Section_LI);
    
                for (var i in Tuner.Sections) {
                    //alert(Tuner.Sections[i].Section + ' ' + Tuner.Sections[i].LI);
                }
    
                for (var i = 0; i <= Tuner.Sections.length - 1; i++) {
                    if (Tuner.Sections[i].Section == "Test") {
                        alert('foudn');
                        Tuner.Sections.splice(i, 1);
                        break;
                    }
                }
    
                for (var i in Tuner.Sections) {
                    //alert(Tuner.Sections[i].Section + ' ' + Tuner.Sections[i].LI);
                }
    
                var myJSON = JSON.stringify(Tuner);
                alert('Done ' + myJSON);
                
            
    
                $.ajax({
                    url: '@Url.Action("Test1")',
                    type: "POST",
                    contentType: "application/json; charset=utf-8",
                    data: JSON.stringify(jsonData),
                    success: function (result) {
                        alert(result.success + " " + result.responseText);
                    },
                    error: function (result) {
                        alert("Failed");
                    }
                });
    
            });
    [HttpPost]
            public ActionResult Test1(Tuner sdata)
            {
                return Json(new { success = true, responseText = "Your message successfuly sent!" }, JsonRequestBehavior.AllowGet);
            }
    public class Tuner
        {
            public string Tick1 { get; set; }
            public string Tick2 { get; set; }
            public List<Sections> Sections { get; set; }
            //public Sections[] Sections { get; set; }
        }
    
        public class Sections
        {
            public string Section { get; set; }
            public string LI { get; set; }
    
        }

    when i pass json like this way data: JSON.stringify({ sdata: Tuner }), then server side action break point hit.

    what is the fault of my code for which action did not hit? thanks

    Wednesday, June 24, 2020 12:59 PM
  • User475983607 posted

    There a bugs in your code.   The main issue is jsonData does not exist in your JavaScript application.

    data: JSON.stringify(jsonData),

    Working Demo.

    public ActionResult Index()
    {
        return View();
    }
    
    [HttpPost]
    public ActionResult Index(Tuner model)
    {
        return Json(model);
    }
    @model MvcDemo.Models.MahkotaVm
    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Index</h2>
    <form method="post">
        <input id="btnSubmit2" type="submit" value="submit" />
    </form>
    @section scripts {
        <script>
            $("#btnSubmit2").click(function (e) {
                e.preventDefault();
    
                var Tuner = {};
                Tuner.Tick1 = 'true';
                Tuner.Tick2 = 'false';
                Tuner.Sections = [];
    
                var Section_LI = {};
                Section_LI.Section='Consensus Model';
                Section_LI.LI = 'Operating Earnings Before Income Taxes';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section='Consensus Model';
                Section_LI.LI = 'Net Income attributable to common, GAAP';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section='Consensus Model';
                Section_LI.LI = 'Diluted Shares Outstanding';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section = 'Test';
                Section_LI.LI = 'Tridip';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section='Consensus Model';
                Section_LI.LI='Operating EPS';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section = 'Segment Details';
                Section_LI.LI = 'Limited Partnership Income-Retirement';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section = 'Segment Details';
                Section_LI.LI = 'Prepayment Fee Income-Retirement';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section = 'Segment Details';
                Section_LI.LI = 'Gross Investment Income-Retirement';
                Tuner.Sections.push(Section_LI);
    
                Section_LI = {};
                Section_LI.Section = 'Segment Details';
                Section_LI.LI = 'Investment Expenses-Retirement';
                Tuner.Sections.push(Section_LI);
    
    
                console.log(Tuner);
    
                $.ajax({
                    url: '@Url.Action("Index")',
                    type: "POST",
                    contentType: "application/json; charset=utf-8",
                    data: JSON.stringify(Tuner),
                    success: function (result) {
                        console.log(result);
                    },
                    error: function (result) {
                        console.log("Failed");
                        console.log(result);
                    }
                });
    
            });
        </script>
        }
    
    
    

    I think you'll be interested in learning how to use the browser to debug JavaScript.

    https://developers.google.com/web/tools/chrome-devtools/javascript/breakpoints

    Wednesday, June 24, 2020 1:40 PM
  • User1686398519 posted

    Hi TDP,

     var myJSON = JSON.stringify(Tuner);

    • I'm sorry I didn't make you understand what I mean.You can check my example again, the data I defined is "jsonData", so the data passed is "JSON.stringify(jsonData)".According to your code, you can see that the data you defined is "Tuner", and you have serialized "Tuner" here, and have been assigned to "myJSON", then you should pass the data should be "myJSON".Your code does not trigger the Test1 action because the parameter type does not correspond.

    For the code you provide, you only need to modify this.

    data: myJSON,
    • when i pass json like this way data: JSON.stringify({ sdata: Tuner }), then server side action break point hit.

    If I write this way, there is no problem, you can check my operation below.

    Best Regards,

    YihuiSun

    Thursday, June 25, 2020 9:30 AM
  • User-454825017 posted

    Thanks now it worked.

    $.ajax({
                    url: '@Url.Action("Test1")',
                    type: "POST",
                    contentType: "application/json; charset=utf-8",
                    data: JSON.stringify(Tuner),
                    success: function (result) {
                        alert(result.success + " " + result.responseText);
                    },
                    error: function (result) {
                        alert("Failed");
                    }
                });

    thanks a lot for your support.

    Thursday, June 25, 2020 2:33 PM