Aspnetcore.docs: Loading a Partial View (or View Component) with a button click and Ajax?

Created on 16 Aug 2018  Â·  16Comments  Â·  Source: dotnet/AspNetCore.Docs

Is it possible in Razor Pages to have a button that calls an Ajax function that in turn fetches the HTML of a Partial View and inserts it into the View without reloading the page?

For example, if I want to load a bunch of new Child form objects into a Parent's list before I submit the Parent form?


Class examples:

public class Parent
{
    public int Id { get; set; }
    public string ParentName { get; set; }
    public List<Child> Children { get; set; }
}

public class Child
{
    public int Id { get; set; }
    public string ChildName { get; set; }
    public int ParentId { get; set; }
}

Html examples:

_Create.cshtml (CreateModel : PageModel with a bound Parent)_

<form method="post">
    <label asp-for="Parent.ParentName"></label>
    <input asp-for="Parent.ParentName" />

    <div id="newChildDiv"></div>

    <input id="addNewChildButton" type="button" value="Add New Child" class="btn btn-default" />
    <input type="submit" value="Create" class="btn btn-primary" />
</form>

_ChildPartialView.cshtml_

<label asp-for="Child.ChildName"></label>
<input asp-for="Child.ChildName" />

In MVC5 I would do this by having a url to a Controller method on a button, along with any parameters in data-* tags that I would pass to an Ajax function and that Controller would return the PartialView (after doing any logic needed) to the Ajax function that would finally insert into a specified HTML element.

This is pretty similar to what I'm describing: MVC 5 BeginCollectionItem with Partial CRUD
I would have to use BeginCollectionItem for this to work, but there is a Core port available too.

Can this be done in Razor Pages still?
Would it be better to do this with View Components?


Document Details

⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

P1 Source - Docs.ms

All 16 comments

Rather than a method in a controller you could have that method in a Razor Page. You could also use a controller - no problem using controllers with Razor Pages.

I must be missing something, I'm not able to return a Partial View from my Razor Page methods.

In my previous MVC 5 project I had a public ActionResult GetChildPartialView(...) method in a Controller that returned PartialView("_partialsName", modelName);

But now in my Razor Page it seems I can't return a PartialView(...) or even a View(...)
Is there new syntax to do this in Razor Pages?

I've also tried to make this method that returns a ViewComponenet:

private async Task<IViewComponentResult> GetParentChildAsync()
 {
    return await new Shared.Components.ViewComponents
        .Child(_context)
        .InvokeAsync(...);
}

but loading the Page gives me this error before it hits the OnGet method:

InvalidOperationException: Unsupported handler method return type 'System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IViewComponentResult]'.

This method, which I took from this MS example, also throws an error:

[BindProperty]
Parent Parent { get; set; }

public IActionResult OnGetTest()
{
    return ViewComponent("Child", new { parentId = Parent.Id });
}

which says

Non-invocable member 'ViewComponent' cannot be used a like a method

I can only find examples online about returning a Partial View or View Component from the .cshtml file using tag helpers or the @Html,RenderPartial(...) syntax, not from .cshtml.cs or by calling a method on from the .cshtml


Regarding URL generation in a view, I figured out I can at least have my Ajax call a Razor Page method, OnGetTest(), by setting the url value like this:

<input id="addNewChildButton" 
    type="button"
    value="Add New Child"
    class="btn btn-default"
    asp-page-handler="Test" />

<script>
let requestVerificationToken = $("input[name='__RequestVerificationToken']").val();
$("#addNewChildButton").click(function () {
    $.ajax({
        type: "GET",
        url: "?handler=" + $("#addNewChildButton").attr("asp-page-handler"),
        headers: {
            "RequestVerificationToken": requestVerificationToken
        }
    }).done(function (data, statusText, xhdr) {
        $("#newChildDiv").after(data);
    }).fail(function (xhdr, statusText, errorText) {
        $("#newChildDiv").text(JSON.stringify(xhdr));
    });
});
</script>

Unsure if there is a better way to handle that

I was able to do what I wanted with a very very basic example in this project using Controllers: https://github.com/RyanTaite/DynamicListExample

But I would still really like to know how to return Partial Views or View Components from a Razor Page method if possible

@RyanTaite You'll probably get a quicker response if you ask on Stack Overflow.

@Rick-Anderson I will likely ask on StackOverflow, but I would really like for the documentation to show an example of calling a Partial View or View Component from a Razor Page method.

Should I close this Issue and open another one requesting that as this issue was originally about performing an Ajax call?

Yes, open a new issue on this doc page. Open it from the doc (as you did this one) - that way others will see it who view the doc.

@RyanTaite have you tried to do this from a ASP.NET Core controller?

@Rick-Anderson Yes, in my demo application that I linked above: https://github.com/RyanTaite/DynamicListExample

It works for the most part:

In Startup.cs's Configure method you have to add:
app.UseMvc(routes => routes.MapRoute("default", "{controller}/{action=Index}/{id?}"));

Then I added a Controller:

using DynamicListExample.Models;
using Microsoft.AspNetCore.Mvc;

namespace DynamicListExample.Controllers
{
    public class ParentController : Controller
    {
        public IActionResult GetChildPartialView()
        {
            return PartialView("_ChildPartialView", new Child());
        }
    }
}

And I can call that with a @Url.Action("GetChildPartialView", "Parent") from my View/Ajax method

I would like to point out that PartialView("_ChildPartialView", new Child()); throws an error saying:

Cannot resolve partial view '_ChildPartialView'

But it actually can. So there will be an error for every PartialView("_somePartialView", ...) method call that you just have to ignore

Changing it to PartialView("Shared/_ChildPartialView", ...) gets rid of the error in Visual Studio, but fails to locate the View when running the application because it's looking for it in a View folder that doesn't exist.
I don't know how to override that behavior.

@rynowak please review.

We've added support for returning a partial directly from a Razor Page in 2.2. I think we should still document any applicable workarounds for prior versions - which part in particular did you want me to review?

/cc @pranavkm

@rynowak I'll need a draft of instruction for prior versions (2.0 and 2.1). I'll also take a draft of 2.2 instructions. Is it supported in 2.2 preview 1?

Fixed by #8493

Hello experts,I want to implement load more button for my website ,https://mrnams.com

Can any one please give idea how to implement load more button to load more videos without refreshing (I mean without loosing loaded videos) page.

Similar to YouTube functionality.

I am using .net core 2.1 version

Hello @mrnams ... You'll get a much faster response if you ask on a support forum, such as Stack Overflow, or a support chat, such as Slack or Gitter.

Hello @mrnams ... You'll get a much faster response if you ask on a support forum, such as Stack Overflow, or a support chat, such as Slack or Gitter.

Thanks

Was this page helpful?
0 / 5 - 0 ratings