0

I have this button in a form:

<button id="save" type="submit" formaction="@Url.Action("SaveEvent")" formmethod="post">Save</button>

Which posts to this controller:

public async Task<ActionResult> SaveEventAsync(EventDataModel vm)
{
    // save to db etc...
    TempData["Saved"] = true;
    return RedirectToActionWithReturnUrl("EventDetail", new { eventId = vm.EventId });
}

This redirects me fine to the detail page. But if I then add this JS function to do the post, I don't get redirected nor do I see the value in TempData.

$('#save').click(function(e){
    e.preventDefault();
    $.post( "SaveEvent", {
        EventID: "@Model.EventId",
        SomeValue: 123
    });
}

I tried redirecting in the JS function but it doesn't return me the newly saved values:

window.location = '@Html.Raw(@Url.Action("EventDetail", new { eventId = @Model.EventId}))';

Could someone please explain why the redirect in the controller does not work when posting from JS?

Graeme
  • 2,597
  • 8
  • 37
  • 50
  • Never heard of `RedirectToActionWithReturnUrl` method ! Is that your custom method ? What it does ? – Shyju Jan 25 '16 at 17:28
  • It could be because your SaveEventAsync is expecting an object of type EventDataModel which you are not passing to it. – krilovich Jan 25 '16 at 17:37
  • remove `e.preventDefault();` – Ruben Yeghikyan Jan 25 '16 at 17:37
  • You cannot return `RedirectResult` in ajax request – Gene R Jan 25 '16 at 17:39
  • Yes, ReturnToActionWithReturnUrl is a custom method which simply adds a URL to the RouteValues. Not sure why as I didn't write it :-). I understand now that RedirectResult cannot be returned to an ajax request. Thanks to Shyju for the code sample. Works fine. – Graeme Jan 25 '16 at 18:51

1 Answers1

0

The Redirect related methods in controller (Redirect,RedirectToAction etc) returns a 302 response with the new url to be redirected to as the value of the location header and browsers will usually issue a new GET request to that.

You should not be making the call to an action method which returns a 302 response from an ajax call. Instead, you should return a json response to the ajax call which is making the request.

public async Task<ActionResult> SaveEventAsync(EventDataModel vm)
{
    // save to db etc...  
    return Json(new {status = "success"});    
}

and in your $.post method callback, inspect the response and do the redirection.

$('#save').click(function(e){

    e.preventDefault();

    var url="@Url.Action("SaveEvent","YourControllerName")";

    $.post(url, { EventID: "@Model.EventId", SomeValue: 123 }, function(res){
        if (res.status === "success") {
           window.location.href =" @Url.Action("EventDetail","YourControllerName",
                                                          new { eventId=Model.EventId })";
        }
    });

});

I updated your code to use Url.Action method to build the correct relative url to the action method(s). If you javascript code is inside a separate js file, build the base url in your razor page and pass to your js code as explained in this post.

Community
  • 1
  • 1
Shyju
  • 214,206
  • 104
  • 411
  • 497