简体   繁体   中英

HTML.Partial not firing controller method in ASP.NET Core

Why is my html.partial not firing the Create method in controller?

Here is my chtml code:

<div class="modal fade" id="UnitModal">
    <div class="modal-dialog">
        <div class="modal-content">
            @Html.Partial("Create")
        </div>
        <!-- /.modal-content -->
    </div>
    <!-- /.modal-dialog -->
</div>
<!-- /.modal -->

Here is my code in controller:

// GET: Units/Create
public IActionResult Create()
{
    return View();
}

// POST: Units/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(UnitViewModel unit)
{
    if (ModelState.IsValid)
    {
        var model = _mapper.Map<Unit>(unit);
        _context.Add(model);

        await _context.SaveChangesAsync();

        return RedirectToAction(nameof(Index));
    }

    return View(unit);
}

Every time I click the button to display the create modal, Get Create from controller is not firing. But Post Create is firing, and properly saving the data. What am I missing?

Sample output:

Sample flow, Get Create not firing

@Html.Partial() takes the view name not the action name. So @Html.Partial("Create") will only render the partial view called "Create".

If you want to execute controller actions, use @Html.Action("create", "units") or @Html.RenderAction("create", "units") instead.


If you're using ASP.NET Core MVC, you can also use View Component .

The Html.Partial will only render the special view, it will not calling the action method (Get method).

To execute the controller action and render the partial view in Asp.net Core, as David said, you could use the View Components . Besides, you could also refer the following steps to use @Html.RenderAction() method in asp.net Core MVC application.

  1. Add a TagHelpers folder in application root path, then, add the HtmlHelperViewExtensions.cs file:

     public static class HtmlHelperViewExtensions { public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, object parameters = null) { var controller = (string)helper.ViewContext.RouteData.Values["controller"]; return RenderAction(helper, action, controller, parameters); } public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, string controller, object parameters = null) { var area = (string)helper.ViewContext.RouteData.Values["area"]; return RenderAction(helper, action, controller, area, parameters); } public static IHtmlContent RenderAction(this IHtmlHelper helper, string action, string controller, string area, object parameters = null) { if (action == null) throw new ArgumentNullException(nameof(controller)); if (controller == null) throw new ArgumentNullException(nameof(action)); var task = RenderActionAsync(helper, action, controller, area, parameters); return task.Result; } private static async Task<IHtmlContent> RenderActionAsync(this IHtmlHelper helper, string action, string controller, string area, object parameters = null) { // fetching required services for invocation var currentHttpContext = helper.ViewContext.HttpContext; var httpContextFactory = GetServiceOrFail<IHttpContextFactory>(currentHttpContext); var actionInvokerFactory = GetServiceOrFail<IActionInvokerFactory>(currentHttpContext); var actionSelector = GetServiceOrFail<IActionDescriptorCollectionProvider>(currentHttpContext); // creating new action invocation context var routeData = new RouteData(); var routeParams = new RouteValueDictionary(parameters?? new { }); var routeValues = new RouteValueDictionary(new { area, controller, action }); var newHttpContext = httpContextFactory.Create(currentHttpContext.Features); newHttpContext.Response.Body = new MemoryStream(); foreach (var router in helper.ViewContext.RouteData.Routers) routeData.PushState(router, null, null); routeData.PushState(null, routeValues, null); routeData.PushState(null, routeParams, null); var actionDescriptor = actionSelector.ActionDescriptors.Items.First(i => i.RouteValues["Controller"] == controller && i.RouteValues["Action"] == action); var actionContext = new ActionContext(newHttpContext, routeData, actionDescriptor); // invoke action and retreive the response body var invoker = actionInvokerFactory.CreateInvoker(actionContext); string content = null; await invoker.InvokeAsync().ContinueWith(task => { if (task.IsFaulted) { content = task.Exception.Message; } else if (task.IsCompleted) { newHttpContext.Response.Body.Position = 0; using (var reader = new StreamReader(newHttpContext.Response.Body)) content = reader.ReadToEnd(); } }); return new HtmlString(content); } private static TService GetServiceOrFail<TService>(HttpContext httpContext) { if (httpContext == null) throw new ArgumentNullException(nameof(httpContext)); var service = httpContext.RequestServices.GetService(typeof(TService)); if (service == null) throw new InvalidOperationException($"Could not locate service: {nameof(TService)}"); return (TService)service; } }
  2. Add the folder reference in the _ViewImports.cshtml

     @using WebApplication2.TagHelpers
  3. Using @Html.RenderAction("<action name>") to load the partial view in the Main View.

[ Note ] By using above method, the action method (partial view) was called when loading the main view, instead of click the "Add Unit" button.

If you want to load the partial view when click the Add button, you'd better to use JQuery to load the partial view. Sample code as below:

        <button type="button" id="btn_addunit" class="btn btn-primary" data-toggle="modal" data-target="#UnitModal">
            Add Unit
        </button>

        <div class="modal fade" id="UnitModal">
            <div class="modal-dialog">
                <div class="modal-content" id="modal_content">

                </div>
                <!-- /.modal-content -->
            </div>
            <!-- /.modal-dialog -->
        </div>
        <!-- /.modal -->

        @section Scripts{ 
            <script type="text/javascript"> 
                    $(document).ready(function () {
                        $("#btn_addunit").click(function () {
                            $("#modal_content").load("/Home/Create"); //change the controller action to yours.
                        });

                }); 
        </script>
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM