15

Index.html (View)

<div class="categories_content_container">
    @Html.Action("_AddCategory", "Categories")
</div>

_AddCategory.cshtml (PartialView)

<script>
    $(document).ready(function () {
        $('input[type=submit]').click(function (e) {
            e.preventDefault();
            $.ajax({
                type: "POST",
                url: '@Url.Action("_AddCategory", "Categories")',
                dataType: "json",
                data: $('form').serialize(),
                success: function (result) {
                    $(".categories_content_container").html(result);
                },
                error: function () {

                }
            });
        });
    });
</script>

@using (Html.BeginForm())
{
    // form elements
}

Controller

[HttpPost]
public ActionResult _AddCategory(CategoriesViewModel viewModel)
{
    if(//success)
    {
        // DbOperations...
        return RedirectToAction("Categories");
    }
    else
    {
        // model state is not valid...
        return PartialView(viewModel);
    }
}

Question: If operation is success I expect that redirect to another page (Categories). But no action, no error message. If operation is not success, it is working like my expected.

How can I do this? How can I route another page with using AJAX post?

pb2q
  • 58,613
  • 19
  • 146
  • 147
AliRıza Adıyahşi
  • 15,658
  • 24
  • 115
  • 197
  • did you already try to add a redirect? your question implies yes but i see no functionality like this in your code. – Dave Alperovich Feb 02 '13 at 22:45
  • OIC, you're trying to redirect inside your action – Dave Alperovich Feb 02 '13 at 22:59
  • @DaveA, I mean in controller success, not ajax. I add `return RedirectToAction("Categories");` to redirect. If model state is not valid ajax post is success (this is expected). I want to redirect in controller action, is this possible? or if not, How can I catch this in ajax success and redirect to another page. summary, I want if DbOperations is success redirect another page else load partialView with model, again. – AliRıza Adıyahşi Feb 02 '13 at 23:01

2 Answers2

32

Don't redirect from controller actions that are invoked with AJAX. It's useless. You could return the url you want to redirect to as a JsonResult:

[HttpPost]
public ActionResult _AddCategory(CategoriesViewModel viewModel)
{
    if(//success)
    {
        // DbOperations...
        return Json(new { redirectTo = Url.Action("Categories") });
    }
    else
    {
        // model state is not valid...
        return PartialView(viewModel);
    }
}

and then on the client test for the presence of this url and act accordingly:

$.ajax({
    type: "POST",
    url: '@Url.Action("_AddCategory", "Categories")',
    data: $('form').serialize(),
    success: function (result) {
        if (result.redirectTo) { 
            // The operation was a success on the server as it returned
            // a JSON objet with an url property pointing to the location
            // you would like to redirect to => now use the window.location.href
            // property to redirect the client to this location
            window.location.href = result.redirectTo;
        } else {
            // The server returned a partial view => let's refresh
            // the corresponding section of our DOM with it
            $(".categories_content_container").html(result);
        }
    },
    error: function () {

    }
});

Also notice that I have gotten rid of the dataType: 'json' parameter from your $.ajax() call. That's extremely important as we are not always returning JSON (in your case you were never returning JSON so this parameter was absolutely wrong). In my example we return JSON only in the case of a success and text/html (PartialView) in the case of failure. So you should leave jQuery simply use the Content-Type HTTP response header returned by the server to automatically deduce the type and parse the result parameter passed to your success callback accordingly.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
5

The ajax call you made should not be able to redirect the whole page. It returns data to your asynchronous call only. If you want to perform a redirect, i

the javascript way to redirect is with window.location

So your ajax call should look like this:

<script>
    $(document).ready(function () {
        $('input[type=submit]').click(function (e) {
            e.preventDefault();
            $.ajax({
                type: "POST",
                url: '@Url.Action("_AddCategory", "Categories")',
                dataType: "json",
                data: $('form').serialize(),
                success: function (result) {
                    window.location='@Url.Action("Categories")';
                },
                error: function () {

                }
            });
        });
    });
</script>

In you action method, instead of returning a partial or redirect, return Json(true);

public ActionResult _AddCategory(CategoriesViewModel viewModel)
{
    if(//success)
    {
        return Json(true);
    }
    else
    {
        return Json(false);
    }
}
Dave Alperovich
  • 32,320
  • 8
  • 79
  • 101