Solved

MVC Ajax.BeginForm how to handle OnSuccess and OnFailure from Controller?

Posted on 2014-12-17
8
11,915 Views
Last Modified: 2014-12-18
Hello all,

I am trying to do something a different way with Ajax posting.   I have a MVC Razor form with an Ajax.BeginForm on it and submit button.   When I click submit I get into my Save action in the Controller.   I can't find a good example on how to handle the Controller action.   I have an OnSuccess and OnFailure in the BeginForm such as this:

@using (Ajax.BeginForm("SaveContact", "Contact", new AjaxOptions { HttpMethod = "Post", OnSuccess = "alert('success');", OnFailure = "alert('failure');" }))

What I actually want to do is call a JavaScript function on the OnSuccess or OnFailure and if Failure I want to somehow pass the error message from the Catch statement in the controller so I can display that in a div tag on the view.  So if it hits the catch (Exception e) I want to pass the e.Message back to the view to display in a div tag.   The problem is I don't know how to handle the controller method on Save if its a ActionMethod or a JsonResult etc.

Can anyone provide a quick example on how to handle the controller method and to get that back to the view?   I cant even find a good example on how to pass back so the OnSuccess or OnFailure gets called after my Save in the controller.

Thanks All.
0
Comment
Question by:sbornstein2
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
8 Comments
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 40506764
Basically if you send anything back with a StatusCode of anything other than 200 it will trigger the OnFailure procedure.

Example:
// view
@using (Ajax.BeginForm(new AjaxOptions { OnSuccess = "OnSuccess", OnFailure = "OnFailure" })) {
    <input type="text" id="name" name="name" />
    <input type="submit" />
}

<script language="javascript" type="text/javascript">
    function OnSuccess(data) {
        alert(data);
    }

    function OnFailure(xhr, status) {
        alert('Error: '+xhr.statusText);
    }
</script>

Open in new window

Sample controller action to trigger OnFailure:
[HttpPost]
public ActionResult Index(string name)
{
    return new HttpStatusCodeResult(404, "Can't find that");
}

Open in new window

0
 

Author Comment

by:sbornstein2
ID: 40506880
Hi Carl so what would I pass back in the controller after I make the save for example?  Is the status code the common thing to pass back at the view?   I had a way using the RazorViewEngine that essentially passed back a partial view as a string and it then refreshed the view itself all ajax.  Works real nice but its confusing to some so I want to dumb it down make it cleaner.
0
 

Author Comment

by:sbornstein2
ID: 40506932
Carl I was just thinking that on the save if success I actually need to pass back the viewmodel to the view based on if they click save again the identity column a HiddenFor I need populated if they click the save button again it should act as an update.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 52

Expert Comment

by:Carl Tawn
ID: 40506958
In that case it might be just as easy to use a full postback rather an Ajax postback.  If you want to use Ajax, then i'd suggest wrapping your editor as a partial view; that way you can save your model, and then return a PartialView with the  updated model and switch it out in your page.

I can put together a basic example if you need it.
0
 

Author Comment

by:sbornstein2
ID: 40506978
That would be great.  What I am thinking not sure it makes sense.  I will have a div tag at the top of my view that will act as a status bar and show an error message.   In the scenario I have a view that has a grid on it and the 1st col has a detail link that takes the user to a data entry form for save.   On success I actually prob want to redirect them back to the grid master.   I could use a Ajax.BeginForm on failure I pass back the response status and keep them on the data entry page.   On success save I pass back to the success a Json Url that on the client I perform a window.location to the Url back to the grid master.   That seem feasible or senseless based on the redirect anyway?  I am just thinking on failure to stay on the page and show the error from the server.
0
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 40507006
You could simply perform a RedirectToAction() if the save is successful (essentially sending the user back to a different page) or return an error to the current view otherwise.

Like:
[HttpPost]
public ActionResult Save(Person model)
{
    try
    {
           repository.Save(model);      // do something to save the model

           // save successful so redirect
           return RedirectToAction("Index");
    }
    catch (Exception ex)
    {
         // save failed so return error to view
         return new HttpStatusCodeResult(404, "Broken");
    }
}

Open in new window

0
 
LVL 52

Accepted Solution

by:
Carl Tawn earned 500 total points
ID: 40507131
Anyway, while you're thinking about which way to go, here's a simple example of how you would do in-line create/edit using a partial view.

First, a simple model:
public class Person
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Open in new window

Then the controller:
public class HomeController : Controller
{
    //
    // GET: /Home/

    public ActionResult Index()
    {
        // create a new, empty, model (ID of -1 indicates it is new)
        Person model = new Person { ID = -1 };
        return View(model);
    }

    [HttpPost]
    public ActionResult Save(Person model)
    {
        // pretend we have saved it somewhere by giving it a non-negative ID
        model.ID = 1;

        ModelState.Clear();

        // re-render the partial view and return
        return PartialView("PersonPartialView", model);
    }
}

Open in new window

Next the PartialView (named PersonPartialView in this case):
@model MvcApplication1.Models.Person

@Html.HiddenFor(model => model.ID)     
<span>@Model.ID</span>      <!-- extra label purely to make it easier to see the ID for demo purposes -->
<div>
    <span>First name: </span>
    @Html.TextBoxFor(model => model.FirstName)
</div>
<div>
    <span>Last name: </span>
    @Html.TextBoxFor(model => model.LastName)
</div>

Open in new window

And finally the main View:
@model MvcApplication1.Models.Person

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@using (Ajax.BeginForm("Save", new AjaxOptions { HttpMethod = "POST", OnSuccess = "OnSuccess", OnFailure = "OnFailure" }))
{
    <div id="container">
        @{ Html.RenderPartial("PersonPartialView", Model); }
    </div>
    <input type="submit" />
}

<script language="javascript" type="text/javascript">
    function OnSuccess(data) {
        $("#container").html(data);
    }

    function OnFailure(xhr, status) {
        alert('Error: '+xhr.statusText);
    }
</script>

Open in new window

So basically this lets us create a new "Person", fill in the details and submit it.  We switch out the updated model so it reflects the update to the ID.  Then, if we click Save again we post back the current ID so we can update the record.
0
 

Author Closing Comment

by:sbornstein2
ID: 40507441
awesome info thanks so much Carl
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Introduction Chart.js, used properly, can visually add a difference to your charting applications. It engages your visitors and allows them to interact with data they otherwise wouldn't be able to without expensive and complicated systems. For this…
The article shows the basic steps of integrating an HTML theme template into an ASP.NET MVC project
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question