asp.net-coreasp.net-core-mvc

Render ASP.NET Core PartialView based on one dataset


I have an old project using ASP.NET Core MVC, I want to create a master/view Razor page as shown in the following screenshot:

enter image description here

To show this page, I have a model with all the details for each record.

Because the data is fetched from a long-running stored procedure, I want to read the stored procedure and pass the model to the page.

When a user clicks on a row, I want to display the details using the data in the model without rereading the database.

I know I can use a partial view passing the model. What I don't know is how to read the row from the model without refreshing the page and rereading the data again.


Solution

  • You can submit a request with the data: selected row's object as query string to Partial View action. Then when the response is returned for the Partial View, you can replace the container that wraps the Partial View.

    1. Set the serialized object in the data-log attribute.
    @using System.Text.Json
    @using Models = <Project namespace model>
    @model List<Models.LogModel>
    
    <table class="table table-bordered">
        <thead>
            <tr>
                <td>Date</td>
                <td>Level</td>
                <td>Queue ID</td>
                <td>Policy Reference</td>
                <td>API Status Code</td>
            </tr>
        </thead>
        <tbody>
            @foreach (var log in Model)
            {
                var json = JsonSerializer.Serialize(log);
                <tr>
                    <td>@log.Date</td>
                    <td>@log.Level</td>
                    <td>@log.QueueID</td>
                    <td>@log.PolicyReference</td>
                    <td>@log.ApiStatusCode</td>
                    <td>
                        <button class="log btn btn-primary" data-log='@Html.Raw(json)'>Select</button>
                    </td>
                </tr>
            }
        </tbody>
    </table>
    
    <div id="detailsContainer" style="padding-top: 30px;">
        @Html.Partial("Details", (Models.LogModel)null)
    </div>
    
    1. A button click listener via jQuery, obtain the serialized JSON from data-log attribute and deserialize it. Then sends the request by passing the object as query string. When the response is returned successfully, set the HTML content for detailsContainer.
    $(document).ready(function () {
        $(".log").click(function () {
            const json = $(this).attr('data-log');
            const log = JSON.parse(json);
            const query = buildQueryString(log);
    
            $.ajax({
                url: `/Log/Details?${query}`,
                type: 'GET',
                success: function (html) {
                    $("#detailsContainer").html(html);
                },
                error: function (xhr, status, error) {
                    console.error("Error loading Details:", error);
                }
            });
        });
    });
    
    function buildQueryString(obj) {
        return Object.entries(obj)
            .map(([key, val]) => encodeURIComponent(key) + '=' + (val ? encodeURIComponent(val) : ""))
            .join('&');
    }
    
    1. Your Details action expects the parameters from the query string as below:
    public IActionResult Details(LogModel model)
    {
        return PartialView("Details", model);
    }
    
    1. And the Details View:
    @model <Project namespace model>.LogModel
    
    <h2>Details</h2>
    
    @if (Model != null)
    {
        <div>
            <label>Date:</label>
            <span>@Model.Date.ToString("yyyy-MM-dd HH:mm:ss")</span>
        </div>
        <div>
            <label>Level:</label>
            <span>@Model.Level</span>
        </div>
        <div>
            <label>Queue ID:</label>
            <span>@Model.QueueID</span>
        </div>
        <div>
            <label>Policy Reference:</label>
            <span>@Model.PolicyReference</span>
        </div>
    }