Search code examples
c#asp.net-mvcrenderaction

Error System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper on @Html.RenderAction after submit the data


I'm trying to use @Html.RenderAction to display Create View in Index View, so that it will be displayed in one page.

User input a first name, last name, etc and click the create button to submit the data and then a new record is added to the table below by reloading the Index View (without AJAX).

When I clicked the Create button to add a new record, I've got the following error:

Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'.

on the @{ Html.RenderAction("Create"); } script after the record is added to the database and redirect to Index View.

What I'm doing wrong here? Is it possible to use RenderAction in this way? It is quite strange when I clicked the create button it will hit the Index Action first and then Create(Post) Action, why not directly hit the Action (Post)?

Here is the code:

Index View:

@model IEnumerable<MailMerge.ViewModels.EmployeeIndexViewModel>

@{
    ViewBag.Title = "Home Page";
}

@{ Html.RenderAction("Create"); }

<h2>List</h2>

<table class="table">
    <thead>
        <tr>
            <th>@Html.DisplayNameFor(m => m.FirstName)</th>
            <th>@Html.DisplayNameFor(m => m.LastName)</th>
            <th>@Html.DisplayNameFor(m => m.Address)</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.FirstName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.LastName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Address)
                </td>
            </tr>
        }
    </tbody>
</table>

Create View:

@model MailMerge.ViewModels.EmployeeCreateViewModel

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <div class="form-group">
            @Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.FirstName)
                @Html.ValidationMessageFor(model => model.FirstName)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.LastName)
                @Html.ValidationMessageFor(model => model.LastName)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Address, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Address)
                @Html.ValidationMessageFor(model => model.Address)
            </div>
        </div>

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

Controller:

public class HomeController : Controller
{
    TestEntities db = new TestEntities();

    public ActionResult Index()
    {
        var employees = db.Employees.ToList();

        List<EmployeeIndexViewModel> employeesVM = new List<EmployeeIndexViewModel>();

        foreach (Employee employee in employees)
        {
            employeesVM.Add(new EmployeeIndexViewModel
            {
                ID = employee.ID,
                FirstName = employee.FirstName,
                LastName = employee.LastName,
                Address = employee.Address
            });
        }

        return View(employeesVM);
    }

    public ActionResult Create()
    {
        EmployeeCreateViewModel employeeVM = new EmployeeCreateViewModel();

        return PartialView("_Create", employeeVM);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(EmployeeCreateViewModel employeeVM)
    {
        if (ModelState.IsValid)
        {
            Employee employee = new Employee();
            employee.FirstName = employeeVM.FirstName;
            employee.LastName = employeeVM.LastName;
            employee.Address = employeeVM.Address;

            db.Employees.Add(employee);
            db.SaveChanges();

            return RedirectToAction("Index");
        }

        return PartialView("_Create", employeeVM);
    }
}

Solution

  • Even though you are posting from your partial view it is inside of the index view and under it's route. If you want to post to a different view you need to set your form action to post to that view on submit.

    <form method="post" action="@Url.Action("Create", "Home")" >