1

I have a fairly simple single-page application that uses AJAX to load and replace contents of the page. The application should allow user to add phone numbers to a customer. After user loads a view to add a new phone number by clicking on Ajax.ActionLink on customers page he can submit an AJAX form with a number to be added, and if the value is a number he should be redirected back to the customers page. Here is where I stuck, how do I return a result of another action? It seems that I can't use RedirectToAction since it returns 302 and the browser initiates a GET request which is not allowed verb in my situation, the browser gets back 404 as a result.

So I have two controllers, PhoneBookController and CustomersController. User loads Customers/Details view and clicks on Ajax.ActionLink which calls PhoneBook/Add action, this action returns a view with an AJAX form which is being submitted to PhoneBook/Create action.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Phone ph, string Caller)
{
    if (ModelState.IsValid)
    {
        ph.Active = true;
        db.PhoneBook.Add(ph);
        db.SaveChanges();
 /*->*/ return RedirectToAction("Details", "Customers", new { Id = ph.CustomerId }); //what should be used instead?
    }

    return PartialView("Add", ph);
}

How this type of tasks usually are accomplished?

hutchonoid
  • 32,982
  • 15
  • 99
  • 104
Jyrkka
  • 526
  • 1
  • 8
  • 26

1 Answers1

1

As you are using ajax, you could return the URL from your action and have it redirected in javascript:

Controller

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Phone ph, string Caller)
{
    if (ModelState.IsValid)
    {
        ph.Active = true;
        db.PhoneBook.Add(ph);
        db.SaveChanges();
    return Json(new { success = true, redirecturl = Url.Action("RedirectedAction") });
}

When you define your ActionLink, specify the success handler:

new AjaxOptions
{
     OnSuccess = "onSuccess"
}

JavaScript

function onSuccess(result) {
    if (result.success == true)
    {
        window.location = result.redirecturl;
    }
}
hutchonoid
  • 32,982
  • 15
  • 99
  • 104
  • Well it's shouldn't be the `window.location` but I've got your idea. The only problem here that if the `ModelState.IsValid` I'm going to send back `JSON` and if not, then the same view should be loaded with validation errors. and how do I understand which one was returned? `Ajax.ActionLink("Add New Number", "", new AjaxOptions{ HttpMethod = "POST", UpdateTargetId = "main-content", Url = Url.Action("Add", "PhoneBook", new { CustomerId = Model.BaseCustomer.Id })})`, so I can add lets say `OnSuccess = "(function (response) { ... })(data)"` but how to tell what the response bears a view or an URL? – Jyrkka May 05 '15 at 12:56
  • @Jyrkka I would just pass the json data back and update the UI afterwards. You can output validation errors in this way: http://stackoverflow.com/questions/28987752/jquery-post-and-unobtrusive-ajax-validation-not-working-mvc-4/28989183#28989183 – hutchonoid May 05 '15 at 13:00
  • It seems that I need your help here also, obviously `$.validator.unobtrusive.parse($form)` cannot be used since $form is not defined. if I pass in the `document` instead of `$form`, error messages are shown only after second click on the submit button? – Jyrkka May 06 '15 at 11:16
  • @Jyrkka it's basically just the form returned with jQuery i.e. `$form = $('form');` or another selector. – hutchonoid May 06 '15 at 11:26
  • I thought that it is, but it didn't work as I expected...Do you have an idea, why the errors dodn't appear before second submit? – Jyrkka May 06 '15 at 11:38
  • @Jyrkka Sorry, I don't. It's worth creating another question, just that way someone else will answer and might have a better idea. A simple example improves the chances of an answer too. – hutchonoid May 06 '15 at 12:00