Reputation: 1822
I currently have a JSON object on my page which gets built up as users add items to it. This is all done in JavaScript/jQuery.
When the user is done adding items, I want to POST this object to a controller action and have the action return a strongly typed view using this data.
Currently, I have the jQuery.ajax POST sending this JSON object to an Action Method which then binds this object to my strongly typed Model. Problem is, I actually want this jQuery.ajax POST to redirect as if the JSON object were in a FORM and simply being submitted.
I also can't use the jQuery.post() method, which would redirect as required, as I need to be able to set the contentType to "application/json" so my binding works correctly. Unfortunately, the jQuery.post() method doesn't allow you to set this parameter.
I've read that the jQuery.post() method basically uses the jQuery.ajax() method, so I've been battling to get the jQuery.ajax() method to redirect.
I've also read that I can set the default contentType for all jQuery.ajax() methods which would then allow me to use the jQuery.post() method but want to try avoid this if possible.
Thanks
Edit: Updated with Saedeas suggestion:
My JavaScript on the 'Index' View:
<script language="javascript" type="text/javascript">
// Initialize the Shopping Cart object
var m_ShoppingCart = {
UserId: 10,
DeliveryInstructions: "Leave at front desk",
CartItems: []
};
$(document).ready(function () {
$.extend({
postJSON: function (url, data, callback) {
return $.ajax({
type: "POST",
url: url,
data: JSON.stringify(data),
success: callback,
dataType: "json",
contentType: "application/json",
processData: false
});
}
});
});
function PostDataWithRedirect() {
var url = '@Url.Action("ConfirmOrder", "Store")';
$.postJSON(url, m_ShoppingCart, function () { });
}
function AddToCart(id, itemName, price, quantity) {
// Add the item to the shopping cart object
m_ShoppingCart.CartItems.push({
"Id": id,
"ItemName": itemName,
"Price": price.toFixed(2), // Issue here if you don't specify the decimal place
"Quantity": quantity
});
// Render the shopping cart object
RenderShoppingCart();
}
function RenderShoppingCart() {
$("#CartItemList").html("");
var totalAmount = 0;
$.each(m_ShoppingCart.CartItems, function (index, cartItem) {
var itemTotal = Number(cartItem.Price) * Number(cartItem.Quantity);
totalAmount += itemTotal;
$("#CartItemList").append("<li>" + cartItem.ItemName + " - $" + itemTotal.toFixed(2) + "</li>");
});
$("#TotalAmount").html("$" + totalAmount.toFixed(2));
}
</script>
And then the Controller Action 'ConfirmOrder'
[HttpPost]
public ActionResult ConfirmOrder(ShoppingCartModel model)
{
return View(model);
}
So when the PostDataWithRedirect() JavaScript method is called it must hit the ConfirmOrder Controller Action and be redirected to the ConfirmOrder View. The Shopping Cart object on my Index view is built up entirely in JavaScript and the user then clicks a 'Proceed to Checkout' button and is redirected etc.
PS: My full working example can be found in an the article [ How to POST a JSON object in MVC ], I just need to update this code so that it can do the post and redirect as explained above
Upvotes: 3
Views: 6545
Reputation: 82267
Return a view that redirects:
controller
return View("redirectionView");
view
RedirectionView.cshtml
@{
Layout = null;
}
<script type="text/javascript">
alert("Success! Redirecting...");
window.location = "./";
</script>
EDIT
To accommodate data retention use tempdata.
controller
TempData["collectedUserData"] = collectedData;
return View("redirectionView");
RedirectionView.cshtml
@{
Layout = null;
}
<script type="text/javascript">
alert("Success! Redirecting...");
window.location = "./Rebuilder/ActionMethod";
</script>
Controller Rebuilder
public ActionResult ActionMethod()
{
if( TempData.ContainsKey("collectedUserData") )
{
var collectedData = TempData["collectedUserData"];
}
//todo: use else clause to catch data not present
use collectedData to build new view
return View();
}
Upvotes: 4
Reputation: 1578
Maybe I'm not following the question, but why does the classic post, redirect, get pattern not work?
[HttpGet]
public ActionResult WhateverActionName()
{
YourViewModel yvm = new YourViewModel();
//Initalize viewmodel here
Return view(yvm);
}
[HttpPost]
public ActionResult WhateverActionName(YourViewModel yvm)
{
if (ModelState.IsValid) {
RedirectToAction("OtherAction", "OtherController")
}
return View(yvm);
}
Do you mean you want to do a post, have it bind to the viewmodel for validation purposes in one controller, and then have that controller post to another controller that verifies everything? If so, I suggest taking a look at this code to post in c# http://geekswithblogs.net/rakker/archive/2006/04/21/76044.aspx.
Edit: Or you could just place the data in a tempdata object if the other controller action doesn't truly require a post.
Edit 2: Wait, is the question how to do the post with jquery? If so,
$("#YourForm").submit(function () {
$.post('@Url.Action("WhateverActionName", "YourController")';
});
});
Note: may be small syntax errors, but close to that. The @Url.Action is the important part.
Edit 3: This should finally work.
jQuery.extend({
postJSON: function(url, data, callback) {
return jQuery.ajax({
type: "POST",
url: url,
data: JSON.stringify(data),
success: callback,
dataType: "json",
contentType: "application/json",
processData: false
});
}
});
Call it in your view as
$.postJSON('@URL.Action("Action", "Controller")', yourJson, callback)
And then redirect inside the controller.
Upvotes: 2
Reputation: 95030
In the success method, do a location.href = "TARGET LOCATION"
to cause the page to go to TARGET LOCATION
.
$.ajax({
url: myurl,data,
data: myData,
// processData: false, // you may need this option depending on service setup
success: function(){
location.href = "TARGET LOCATION";
},
type: "POST",
contentType: "application/json"
});
Upvotes: 6