Majid
Majid

Reputation: 31

Json Not hitting controller

In My code to save Order JSON not hitting controller also there is no Error appearing even in
Browser Console, Only I am getting Error: Order Not Complete!

My controller:

public ActionResult SaveOrder([FromBody]string name, string address, Order[] order)
 {
 //var settings = new JsonSerializerSettings();

 string result = "Error! Your Order Is Not Complete!";
 try
   {
   if (name != null && address != null && order != null)
     {
     var cutomerId     = Guid.NewGuid();
     Customer model    = new();
     model.CustomerId  = cutomerId;
     model.Name        = name;
     model.Address     = address;
     model.OrderDate   = DateTime.Now;
     db.Customers.Add(model);

     foreach (var item in order)
       {
       var orderId   = Guid.NewGuid();
       Order O       = new();
       O.OrderId     = orderId;
       O.ProductName = item.ProductName;
       O.Quantity    = item.Quantity;
       O.Price       = item.Price;
       O.Amount      = item.Amount;
       O.CustomerId  = cutomerId;
       db.Orders.Add(O);
       }
     db.SaveChanges();
     result = "Successfully! Order Is Complete!";
     }
   return Json(result);
   }
 catch (Exception)
   {
   throw;
   }
 }

And here is the JavaScript Code:

function saveOrder(data) {
  return $.ajax({
    contentType : 'application/json; charset=utf-8',
    dataType    : 'json',
    type        : 'POST',
    url         : "/Orders/SaveOrder",
    data        : data,
    success     : function (result) {
      alert(result);
      location.reload();
    },
    error       : function () {
      alert("Error!")
    }
  });
}

//Collect Multiple Order List For Pass To Controller
$("#saveOrder").click(function (e) {
  e.preventDefault();

  var orderArr = [];
  orderArr.length = 0;
  $.each($("#detailsTable tbody tr"), function () {
    orderArr.push({
      productName : $(this).find('td:eq(0)').html(),
      quantity    : $(this).find('td:eq(1)').html(),
      price       : $(this).find('td:eq(2)').html(),
      amount      : $(this).find('td:eq(3)').html()
    });
  });

  var data = JSON.stringify({
    name    : $("#name").val(),
    address : $("#address").val(),
    order   : orderArr
  });

  $.when(saveOrder(data)).then(function (response) {
    console.log(response);
  }).fail(function (err) {
    console.log(err);
  });
});

I am reading and searching But couldn't find any difference in my code or even knows my mistake, that is why I seeking Help from you please

Upvotes: 1

Views: 443

Answers (2)

Chen
Chen

Reputation: 5114

As @dbc said,you can only have one [FromBody] parameter as the body can only be read once.

I think your error may be due to the incorrect JSON format, the controller does not receive the parameters passed by Ajax, you can check if your Json body is like this when it is passed:

enter image description here

Below is my test code,you can refer to it:

View:

@model _2022072501.Models.OrderDTO

<button id="saveOrder" class="btn btn-primary">submit</button>

<script src="https://code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script>
<script>
    function saveOrder(data) {
       $.ajax({
        contentType : 'application/json; charset=utf-8',
        dataType    : 'json',
        type        : 'POST',
        url         : "/Home/SaveOrder",
        data        : data,
        success     : function (result) {
          alert(result);
          location.reload();
        },
        error       : function () {
          alert("Error!")
        }
      });
    }

//Collect Multiple Order List For Pass To Controller
$("#saveOrder").click(function (e) {
    e.preventDefault();
    debugger;
    var orderArr = [];
    orderArr.push({
      productName : "Test1",
      quantity    : "Test1"
    });
    orderArr.push({
      productName : "Test2",
      quantity    : "Test2"
    });

  var data = JSON.stringify({
    name    : "testName",
    address : "testAdress",
    order   : orderArr
  });

  $.when(saveOrder(data)).then(function (response) {
    console.log(response);
  }).fail(function (err) {
    console.log(err);
  });
});
</script>

Controller:

public IActionResult SaveOrder([FromBody] OrderDTO orderDTO)
{
    //var settings = new JsonSerializerSettings();

    string result = "Error! Your Order Is Not Complete!";
    var (name, address, order) = (orderDTO?.name, orderDTO?.address, orderDTO?.order);
    try
    {
        if (name != null && address != null && order != null)
        {
            foreach (var item in order)
            {
                var orderId = Guid.NewGuid();
                Order O = new();
                O.OrderId = orderId;
                O.ProductName = item.ProductName;
                O.Quantity = item.Quantity;
                //db.Orders.Add(O);
            }
            //db.SaveChanges();
            result = "Successfully! Order Is Complete!";
        }
        return Json(result);
    }
    catch (Exception)
    {
        throw;
    }
}

You can cancel your $.each like me and change it to a fixed value, maybe it's more convenient to find the problem

Upvotes: 0

dbc
dbc

Reputation: 116670

It looks like you are trying to bind all three arguments [FromBody]string name, string address and Order[] order to the JSON body of your request, but as explained in .NET Core Web API: multiple [FromBody]? you can only have one [FromBody] parameter as the body can only be read once.

Instead, create a top-level DTO corresponding to the JSON in your body, and bind to that:

public class SaveOrderRequestModel
{
    public string name { get; set; }
    public string address { get; set; }
    public Order[] order { get; set; }
}

and then

public ActionResult SaveOrder([FromBody] SaveOrderRequestModel saveOrderRequest)        
{
    string result = "Error! Your Order Is Not Complete!";
    var (name, address, order) = (saveOrderRequest?.name, saveOrderRequest?.address, saveOrderRequest?.order);
    if (name != null && address != null && order != null)
    {
        // Proceed as before

Upvotes: 2

Related Questions