Simple Introduction to MVC Ajax (Post 2)

14/09/2014

So far we have seen how to add a very simple ActionLink and attach actions. Now let's load a PartialView using Ajax. Also we want to load a partial view with a different model into our page.

Getting a Partial View using ActionLink

We're going to deal with an object a Dog could "own", so we create a collar class. Let's accessorize our dog with some fabulous collars / add an ActionLink to the Dog/Details view (Details.cshtml):

@Ajax.ActionLink(linkText: "Call An Action Returning a partial view",
    actionName: "GetCollarCreate",
    routeValues: new { id = @Model.Id },
    ajaxOptions: new AjaxOptions
    {
        UpdateTargetId = "ajaxpartialtarget",
        InsertionMode = InsertionMode.Replace
    })
<div id="ajaxpartialtarget"></div>

We can pass the Id of the dog in using RouteValues as normal. The InsertionMode.Replace is default so doesn't need to be defined explicitly, I'm just doing it because it doesn't hurt to be reminded. This ActionLink calls the following method on the Dog Controller (DogController.cs):

public ActionResult GetCollarCreate(int id){
    return RedirectToAction(actionName: "_Create", 
        controllerName: "Collar", 
        routeValues: new { id });
}

This then directs us to an action on our Collar Controller class (CollarController.cs):

[HttpGet]
public PartialViewResult _Create(int id){
    Collar collar = new Collar { DogId = id };
    return PartialView(viewName: "_Create", model: collar);
}

Where our collar is a simple view model:

public class Collar
{
    public int DogId { get; set; }

    public string Color { get; set; }

    public bool HasTag { get; set; }
}

We will create a more detailed view in the next part but for now we have this simple view (Create.cshtml):

@model JunkCode.Collar
<div> Loaded the partial view for dog with Id = @Model.DogId </div>

When we build and run this we get the result we want, the view is loaded using an Ajax request, the dog woofs for joy:

The partial view loads in the div

Hiding the PartialView again

It would be nice to remove the partial view if we change our mind about whatever Action we're calling, I added this link in our Collar/Create view (Create.cshtml):

@Ajax.ActionLink(linkText: "Hide",
    actionName: "_HideCreate",
    ajaxOptions: new AjaxOptions
    { UpdateTargetId = "ajaxpartialtarget" })

This calls the Controller method (CollarControler.cs):

[HttpGet]
public void _HideCreate() { ; }

The coding of the UpdateTargetId into another view is kinda crappy, but I'm sure you can think of a way to improve it if it makes you incandescent with rage.

Loading a form in our PartialView

We modify the "GetCollarCreate" method in our Dog controller to return the results of our new Collar controller method (DogController.cs):

return RedirectToAction(actionName: "_Create2",
        controllerName: "Collar",
        routeValues: new { id });

The _Create2 method returns a PartialView (CollarController.cs):

[HttpGet]
public PartialViewResult _Create2(int id)
{
    Collar collar = new Collar { DogId = id };
    return PartialView(viewName: "_Create2", model: collar);
}

The Create2 view was created by the Scaffolding tool but looks a bit like this (Create2.cshtml):

@model Questions.JunkCode.Collar
@using(Html.BeginForm("_Create2", "Collar", new {}))
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        @Html.ValidationSummary(true)
        <div class="form-group">
            [MORE STUFF HERE...]
        </div>

        <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>

    </div>
    </div>
}
<div id="statusMessage"></div>

We can then define the _Create2 post method in our Collar Controller (CollarController.cs):

[HttpPost]
public string _Create2(int id, Collar model)
{
    // Call some repository method to create the collar
    return "Collar Created!";
}

When we load this controller we get the following result:

The partial view loads a form

Next Post

So far we've used an Ajax ActionLink and loaded an HTML form into our page using Ajax, how about getting the form to submit using Ajax? This is the tricky bit to get right and is the topic of the next post