Search code examples
asp.net-corerazorrazor-pages

Pass Model from Partial View to the PageModel in Asp.Net Core Razor


I am trying to pass a Model from a Partial view back to the PageModel, but the results are always empty. In my main .cshtml, I have an 'Export' button that when clicked opens a bootstrap modal. Users then click a checkbox to select data to download. Here is my code:

In my cs, I set the partial with this code:

// FileContents contains a list of FileObjects (which include Name as IsSelected)
[BindProperty]
public FileContents ExportData { get; set; }

// Get method to return the partial. 
// ExportData is passed as the model for the partial
public PartialViewResult OnGetExportModel()
{
    ExportData = new FileContents();
    ExportData.Files.Add(new FileObject("filename.txt", true);
    return Partial("_ExportDetails", ExportData);
}

// Handles postback of the FileContents data 
public IActionResult OnPostExportData(FileContents data)
{
  //The count is always zero
  Console.WriteLine(data.Files.Count);
}

The partial is a table with the file name and a checkbox:

@model FileContents

<div class="form-group">  
    <table>
        <tbody>
            @foreach (var item in Model.Files)
            {
                <tr>
                    <td class="clsChkBox" data-item="@item.Name">
                        @Html.CheckBoxFor(modelItem => item.IsSelected)
                    </td>
                    <td>@item.Name</td>
                </tr>
            }
        </tbody>
    </table>
</div>

In the main page .cshtml, I display the partial:

<div class="dvExport" id="exportPartial"></div>

The partial is set with a class from a script:

function ScriptExport() {             
    $('.dvExport').load('/index/exportmodel);
}

I have tried several ways to pass the FileContents model of the partial, back to the .cs file.

  • One by using a <form method=post" asp-page-handler="ExportData" asp-route-data="@Model.ExportData"> . When returned, data.Files is empty.
  • Second by calling an ajax postback. When serializing @Model.ExportData, the files are also empty.

How can I return FileContents model in the partial back to my main page?


Solution

  • I did a test using ajax, you can refer to my code below:

    _ExportDetails.cshtml:

    @model FileContents
    
    <div class="form-group">
        <table>
            <tbody>
                @foreach (var item in Model.Files)
                {
                    <tr>
                        <td class="clsChkBox"  data-item="@item.Name">
                            @Html.CheckBoxFor(modelItem => item.IsSelected)
                        </td>
                        //Add a class as an identifier
                        <td class="Name">@item.Name</td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
    

    Index.cshtml:

    @page
    @model IndexModel
    
    @{
        ViewData["Title"] = "Home page";
    }
    <button type="button" onclick="ScriptExport()">ScriptExport</button>
    
    <button type="button" onclick="ScriptSubmit()">Submit</button>
    
    <div class="dvExport" id="exportPartial"></div>
    
    //Required
    <div>@Html.AntiForgeryToken()</div>
    
    <script>
        function ScriptExport() {             
            $('.dvExport').load('index?handler=ExportModel');
        }
    
        function ScriptSubmit(){
            var data = [];
            $("table > tbody > tr").each(function() {
                var Files = {
                    Name: $(this).find('.Name').text(),
                    IsSelected: $(this).find("input[type='checkbox']").prop("checked")
                }
                data.push(Files);
            });
    
            $.ajax({
                type: "post",
                url: "/index?handler=ExportData",
                data: JSON.stringify({ Files: data }),
                //Required
                headers:
                {
                    "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
                },
                contentType: "application/json; charset=utf-8",
                success: function(result)
                {
                    alert("success");
                },
                error: function(error)
                {
                    console.log(error);
                }
            });
        }
    
    </script>
    

    Index.cshtml.cs:

    public IActionResult OnPostExportData([FromBody]FileContents data)
    {
        Console.WriteLine(data.Files.Count);
        return Page();
    }
    

    Test Result: enter image description here enter image description here