Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery Mobile/MVC: Getting the browser URL to change with RedirectToAction

My first post...

When I use RedirectToAction the url in the browser doesn't change. How can I achieve this?

I'm switching over to ASP.NET MVC 3.0 (also using jQuery Mobile) after 10+ years using web forms. I'm about 8 weeks into it, and after several books and scouring Google for an answer, I'm coming up dry.

I have a single route defined in Global.asax:

routes.MapRoute( "Routes", "{controller}/{action}/{id}", new { controller = "Shopping", action = "Index", id = UrlParameter.Optional } 

I have a ShoppingController with these actions:

public ActionResult Cart() {...}  public ActionResult Products(string externalId) {...}  [HttpPost] public ActionResult Products(List<ProductModel> productModels) {     // do stuff     return RedirectToAction("Cart"); } 

The url when I do a get and post (with the post having the RedirectToAction) is always:

/Shopping/Products?ExternalId=GenAdmin 

After the post and RedirectToAction I want the url in the browser to change to:

/Shopping/Cart 

I've tried Redirect, and RedirectToRoute but get the same results.

Any help would be greatly appreciated.

[Update] I found that jQuery Mobile AJAX posts are the culprit here. If I turn off jQuery Mobile's AJAX it works.

<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js"></script> <script type="text/javascript">     // do not handle links via ajax by default     $(document).bind("mobileinit", function () { $.mobile.ajaxEnabled = false; }); </script> <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0rc2/jquery.mobile-1.0rc2.min.css" /> 

The ordering of the above scripts is important. I had to include the script to jQuery first, then include the script to disable jQuery Mobile's use of AJAX and then include the script to jQuery Mobile.

I'd still like to find a way to use AJAX and have the url update properly. Or at the least be able to call jQuery Mobile's "loading" message (or bake my own).

like image 950
David Hoffman Avatar asked Oct 19 '11 15:10

David Hoffman


People also ask

How to use RedirectToAction in MVC?

The RedirectToAction() method makes new requests and URL in the browser's address bar is updated with the generated URL by MVC. Between RedirectToAction() and Redirect() methods, best practice is to use RedirectToAction() for anything dealing with your application actions/controllers.

What is difference between redirect and RedirectToAction?

RedirectToAction is meant for doing 302 redirects within your application and gives you an easier way to work with your route table. Redirect is meant for doing 302 redirects to everything else, specifically external URLs, but you can still redirect within your application, you just have to construct the URLs yourself.

Is RedirectToAction a post or a get?

When you call RedirectToAction within a controller, it automatically redirects using an HTTP GET.


2 Answers

I think I've found an answer. Buried deep in the jQuery Mobile documentation, there is information about setting the data-url on the div with data-role="page". When I do this, I get the nice jQuery Mobile AJAX stuff (page loading message, page transitions) AND I get the url in the browser updated correctly.

Essentially, this is how I'm doing it...

[HttpPost] public ActionResult Products(...) {     // ... add products to cart     TempData["DataUrl"] = "data-url=\"/Cart\"";     return RedirectToAction("Index", "Cart"); } 

Then on my layout page I have this....

<div data-role="page" data-theme="c" @TempData["DataUrl"]> 

On my HttpPost actions I now set the TempData["DataUrl"] so for those pages it gets set and is populated on the layout page. "Get" actions don't set the TempData["DataUrl"] so it doesn't get populated on the layout page in those situtations.

The only thing that doesn't quite work with this, is when you right-click... view source... in the browser, the html isn't always for the page you are on, which isn't unusual for AJAX.

like image 60
David Hoffman Avatar answered Nov 11 '22 13:11

David Hoffman


Not sure if it is still actual, but in my case I wrote following helper method

public static IHtmlString GetPageUrl<TModel>(this HtmlHelper<TModel> htmlHelper, ViewContext viewContext)     {         StringBuilder urlBuilder = new StringBuilder();         urlBuilder.Append("data-url='");         urlBuilder.Append(viewContext.HttpContext.Request.Url.GetComponents(UriComponents.PathAndQuery, UriFormat.UriEscaped));         urlBuilder.Append("'");         return htmlHelper.Raw(urlBuilder.ToString());     } 

And then use it as follows:

<div data-role="page" data-theme="d" @Html.GetPageUrl(ViewContext) > 

This way I don't need for every redirect action store a TempData. Worked for me fine both for Redirect and RedirectToAction. This would not work properly in case if you use method "View()" inside controller and return different view name, which will change UI, but will retain url.

Hope it helps Artem

like image 35
Artem Avatar answered Nov 11 '22 13:11

Artem