chris
chris

Reputation: 121

Changing void method to ActionResult method when there is an Ajax function calling the method

I have recently converted my method from void to an ActionResult so that I can return error messages if a condition isn't met

here is the method

        [HttpPost]
        [ValidateAntiForgeryToken]
        [Audit]
        public ActionResult AddUnits(int so_id, int site_id, int[] addItem_id, int[] addItem_qty, int[] addItem_disc)
        {
            bool canCreate = true;
            string errors = "";

            // Loop however many times is necessary to iterate through the largest array
            for (int i = 0; i < Math.Max(Math.Max(addItem_id.Length); i++)
            {
                foreach (SODetails sod in db.SalesOrders.Find(so_id).SalesDetails)
                {
                    if (i < addItem_id.Length && addItem_qty[i] != 0 && sod.ItemID == addItem_id[i] && addItem_id[i] != 365 && addItem_id[i] != 410) 
                    {
                        sod.item_qty += addItem_qty[i];
                        sod.item_discount = addItem_disc[i];
                        addItem_id[i] = 0;
                        addItem_qty[i] = 0;
                        addItem_disc[i] = 0;
                    }
                }
                db.SaveChanges();

                if(i < addItem_qty.Length && addItem_qty[i] != 0)
                {
                    SODetails sODetails = new SODetails
                    {
                        SalesOrderID = so_id,
                        SiteID = site_id
                    };

                    // Only add a unit to the SODetails object if it's not null and has an id and quanitity specified
                    if(i < addItem_id.Length && addItem_id[i] != 0 && addItem_qty[i] != 0)
                    {
                        sODetails.ItemID = addItem_id[i];
                        sODetails.item_qty = addItem_qty[i];
                        sODetails.item_discount = addItem_disc[i];
                    }

                    if (sODetails.SiteID == 0)
                        sODetails.SiteID = null;

                    // Here on is basically the same as the old post function below
                    SalesOrder SO = db.SalesOrders.Find(sODetails.SalesOrderID);
                    SODetails salesOrderDetails = db.SODetails.Add(sODetails);
                    salesOrderDetails.SalesOrder = SO;

                    Item SO_Item = db.Items.Find(sODetails.ItemID);

                    if (SO_Item != null)
                    {

                        if (SO.OrderType == SOType.OffSiteInventory && salesOrderDetails.siteAvailable(SO_Item) < salesOrderDetails.item_qty)
                        {
                            errors += "Not enough" + SO_Item.Name + "in inventory location";
                            canCreate = false;                           
                        }
                        else { 

                        sODetails.item_qty = sODetails.item_qty == null ? 0 : sODetails.item_qty;
                        int qtyOrdered = sODetails.item_qty == null ? 0 : (int)sODetails.item_qty;
                        salesOrderDetails.dynamicItem_qty = qtyOrdered;

                        if (SO_Item.SalesOrderMessage != null)
                            TempData["SalesOrderMessage"] = SO_Item.SalesOrderMessage;

                        }
                    }

                    if (!canCreate)
                    {
                        ModelState.AddModelError(string.Empty, errors);
                        //return View(so_id);
                        return RedirectToAction("Details", "SODetails", new { orderId = so_id });
                    }

                    db.SODetails.Add(sODetails);                   
                }
            }

            db.SaveChanges();

            return RedirectToAction("Details", "SODetails", new { orderId = so_id });
        }

The method is called through my Ajax function that looks like this

  $.ajax({
            type: "POST",
            url: "@IGT.baseUrl/SODetailsAjax/AddUnits",
            traditional: true,
            data: {
                __RequestVerificationToken: token, 
                so_id: @Int32.Parse(Request["orderId"]),
                site_id: site,
                addItem_id: items,
                addItem_qty: itemsqty,
                addItem_disc: itemsdisc,
                addComp_id: comps,
                addComp_qty: compsqty,
                addComp_disc: compsdisc,
                addPart_id: parts,
                addPart_qty: partsqty,
                addPart_disc: partsdisc
            },
            success: function () {
                location.href = "../SalesOrders/[email protected]";
            },
            error: function (jqXHR, status, error) {
                alert("Error: " + error);
            }
        });

Each time the method is run now it returns error instead of success. How can I change my code so it still returns success if the conditions were valid?

Upvotes: 1

Views: 452

Answers (1)

Dave Barnett
Dave Barnett

Reputation: 2226

If the code is just for ajax then I recommend using Web API instead. Then you would either return Ok or BadRequest. If it could be for both and you want to stay with MVC then you could do this to return a failed request

  if (Request.IsAjaxRequest())
   {
       var result=new { Success="False", Message="Error Message"};
       return Json(result, JsonRequestBehavior.AllowGet);
   }
    else
   {
     //normal mvc error redirect goes here
   }

and this for a succeeded request

  if (Request.IsAjaxRequest())
   {
       var result=new { Success="True"};
       return Json(result, JsonRequestBehavior.AllowGet);
   }
    else
   {
     //normal mvc success redirect goes here
   }

The success code is likely to go at the end of the ActionResult after db.Savechanges() in your code. In your case the normal mvc success redirect would be

return RedirectToAction("Details", "SODetails", new { orderId = so_id });

An example for a failed request would look like this

  if (!canCreate)
  {
     if (Request.IsAjaxRequest())
     {           
         var result=new { Success="False", Message=errors };
         return Json(result, JsonRequestBehavior.AllowGet);
     }
    else
    {
       ModelState.AddModelError(string.Empty, errors);
       return RedirectToAction("Details", "SODetails", new { 
       orderId = so_id });
   }
}

You will also need to update your jQuery to something like this

success: function (data) {
 if(data.Success){
            location.href = "../SalesOrders/[email protected]";
        }else{
        var errorMessage = data.Message;
        //display errorMessage on the client
  }
}

Upvotes: 1

Related Questions