Home > Software engineering >  C# net core 6 How to convert a partial view to json / html string
C# net core 6 How to convert a partial view to json / html string

Time:12-02

I want to refresh a partial view (main) with a single call to reduce the traffic on the network. That one partial view have multiple more partial view (child) inside it. However, I cannot use standard mainpartialview.html(response) approach because one of the child partial view have conflict with the script file. I want to proceed with using JSON however the value inside the model for languageForm and translationForm is empty.The suggestion that I found is require me to use microsoft.aspnetcore.mvc.viewfeatures however it not for Net 6.

Old approach

retun PartialView("~/Views/Facility/Translation/_PanelMain.cshtml", result);

New approach

return Json(new
                {
                    languageForm = PartialView("~/Views/Facility/Translation/_Form_Language.cshtml", result.record),
                    translationForm = PartialView("~/Views/Facility/Translation/_PanelSub.cshtml", result.subRecord),
                    translationViewModel = result.subRecord
                });

From the accepted answer, below is the full solution

C# Controller

[HttpGet]
public async Task<ActionResult> GetLanguageRecord(long? languageID)
{
    LoadViewBag();

    var loadOptions = GetDefaultDataSourceLoadOptions();
    var languageList = _languageService.GetGridViewList(GetMembershipID(), null, loadOptions);
    var translationList = _translationService.GetGridViewList(GetMembershipID(), languageID, loadOptions);

    var result = PopulateViewModel(languageID ?? 0, 0, languageList, translationList, loadOptions);
    result.record.TransactionTypeID = SubmissionType.Edit;

    var services = HttpContext.RequestServices;
    var options = services.GetRequiredService<IOptions<MvcViewOptions>>().Value;
    var executor = (PartialViewResultExecutor)services.GetRequiredService<IActionResultExecutor<PartialViewResult>>();

    return Json(new
    {
        languageForm = await Render(
            options,
            ControllerContext,
            PartialView("~/Views/Facility/Translation/_Form_Language.cshtml", result.record),
            executor),
        translationForm = await Render(
            options,
            ControllerContext,
            PartialView("~/Views/Facility/Translation/_PanelSub.cshtml", result.subRecord),
            executor),
        translationViewModel = result.subRecord
    });
}

Javascript

function grdMain_Language_selection_changed(selectedItems) {

    var data = selectedItems.selectedRowsData[0];
    if (data) {

        $.ajax({
            type: "GET",
            url: "Translation/GetLanguageRecord",
            data: { languageID: data.ID },
            cache: false,
            success: function (response) {
                document.getElementById("_EntryForm_Language").innerHTML = response.languageForm;
                document.getElementById("_SubPanel").innerHTML = response.translationForm; 
                $('#_subPanel_body').collapse('hide');
                $('#_mainPanel_body').collapse('show');

                myData_Translation = response.translationViewModel.recordList;
                myTotalCount_Translation = response.translationViewModel.recordTotal;
                let gvElement_Translation = document.getElementById("grdSub_Translation");
                let gvInstance_Translation = DevExpress.ui.dxDataGrid.getInstance(gvElement_Translation);
                gvInstance_Translation.refresh();
            }
        });

        $(window).scrollTop(0);
    }
}

CodePudding user response:

After a quick look through the internal implementation for return PartialView("viewname");. I think this is the minimum you need to render a partial view into a string;

public async Task<string> Render(MvcViewOptions options, ActionContext context, PartialViewResult result, PartialViewResultExecutor executor)
{
    var viewEngineResult = executor.FindView(context, result);
    viewEngineResult.EnsureSuccessful(originalLocations: null);
    var view = viewEngineResult.View;
    using (view as IDisposable)
    {
        using var writer = new StringWriter();
        var viewContext = new ViewContext(
            context,
            view,
            result.ViewData,
            result.TempData,
            writer,
            options.HtmlHelperOptions);

        await view.RenderAsync(viewContext);
        await writer.FlushAsync();

        return writer.ToString();
    }
}

Which you would use like;

var services = HttpContext.RequestServices;
var options = services.GetRequiredService<IOptions<MvcViewOptions>>().Value;
var executor = (PartialViewResultExecutor)services.GetRequiredService<IActionResultExecutor<PartialViewResult>>();
            
return Json(new {
    languageForm = await Render(
        options,
        ControllerContext,
        PartialView("~/Views/Facility/Translation/_Form_Language.cshtml", result.record),
        executor),
    ...
});

With a bit more effort, you could probably use a Utf8JsonWriter to render each view html directly to the response body without any caching.

  • Related