Exporting Excel Files via Dynamic Form Submissions with JSON Payloads

Initiating a file download via AJAX requests is problematic because the response remains in memory and cannot trigger the browser's save dialog. When dealing with data grids that rely on JSON-based parameters for pagination and filtering, modifying the backend export logic might be restricted. A practical workaround involves constructing a dynamic HTML form, injecting the JSON payload as hidden input fields, and programmatically submitting the form to the server endpoint.

Client-Side Implementation

The JavaScript function below intercepts the grid's current configuration, transforms the JSON object into a sequence of hidden inputs, appends them to a designated form, and executes the submission.

function triggerExcelDownload() {
    const endpoint = "/api/reports/generate";
    const formContainer = document.getElementById("downloadForm");
    formContainer.action = endpoint;
    
    // Remove any previously injected fields
    formContainer.innerHTML = "";

    // Serialize JSON properties into individual form controls
    for (const [key, val] of Object.entries(gridConfiguration)) {
        const hiddenField = document.createElement("input");
        hiddenField.type = "hidden";
        hiddenField.name = key;
        hiddenField.value = val;
        formContainer.appendChild(hiddenField);
    }

    formContainer.submit();
}

Server-Side Parameter Binding

On the server side, the submitted form fields map directly to the expected pagination and filtering properties, eliminating the need for complex JSON deserialization. The backend can process the request using the standard form collection.

public void GenerateReport()
{
    DataFilter criteria = new DataFilter();

    criteria.PageSize = Convert.ToInt32(Request.Form["PageSize"]);
    criteria.Offset = Convert.ToInt32(Request.Form["Offset"]);
    criteria.TotalColumns = Convert.ToInt32(Request.Form["TotalColumns"]);
    criteria.SortColumns = Request.Form["SortColumns"];

    // Apply custom search constraints
    criteria.Keyword = Request.Form["Keyword"];
    criteria.DepartmentId = string.IsNullOrEmpty(Request.Form["DeptId"]) ? Guid.Empty : new Guid(Request.Form["DeptId"]);
    criteria.StartDate = Request.Form["StartDate"];
    criteria.StatusFlag = string.IsNullOrEmpty(Request.Form["Status"]) ? 0 : Convert.ToInt32(Request.Form["Status"]);

    criteria.ApplySorting(Request);
    PageResult<RecordView> dataset = ReportService.FetchPage(criteria);
    BuildExcelDocument(dataset.Items);
}

Excel Document Generation

The export procedure instantiates a workbook, applies an existing template, populates the cells with the retrieved dataset, and streams the resulting file back to the client. It also accounts for browser-specific encoding requirements.

private void BuildExcelDocument(List<RecordView> records)
{
    if (records.Count == 0) return;

    try
    {
        Workbook excelDoc = new Workbook();
        string templatePath = HttpContext.Current.Server.MapPath("~");
        templatePath = templatePath.Substring(0, templatePath.LastIndexOf("\\"));
        templatePath += "/assets/templates/RecordTemplate.xlsx";
        excelDoc.Open(templatePath);

        int rowIndex = 4;
        int sequence = 1;
        Worksheet templateSheet = excelDoc.Worksheets[0];
        excelDoc.Worksheets.Add("ReportData");
        Worksheet targetSheet = excelDoc.Worksheets["ReportData"];
        targetSheet.Copy(templateSheet);

        foreach (var entry in records)
        {
            Cells dataCells = targetSheet.Cells;
            dataCells["A" + rowIndex].PutValue(sequence++);
            dataCells["B" + rowIndex].PutValue(entry.Title);
            dataCells["C" + rowIndex].PutValue(entry.Identifier);
            dataCells["D" + rowIndex].PutValue(entry.CategoryName);
            dataCells["E" + rowIndex].PutValue(entry.EffectiveDate);
            dataCells["F" + rowIndex].PutValue(entry.ExpirationDate);
            dataCells["G" + rowIndex].PutValue(entry.Duration);
            dataCells["H" + rowIndex].PutValue(entry.SupervisorName);
            dataCells["I" + rowIndex].PutValue(entry.StatusDescription);
            dataCells["J" + rowIndex].PutValue(entry.Remarks);
            rowIndex++;
        }

        excelDoc.Worksheets.RemoveAt(0);
        Random rng = new Random();
        string docName = "ReportData" + DateTime.Now.ToString("yyyyMMddHHmmss") + rng.Next(10, 100) + ".xls";

        // Handle URL encoding for legacy browsers
        if (Request.UserAgent.ToLower().Contains("trident"))
        {
            docName = HttpUtility.UrlEncode(docName, Encoding.UTF8);
        }

        excelDoc.Save(docName, FileFormatType.Excel2003, SaveType.OpenInExcel, HttpContext.Current.Response, Encoding.UTF8);
        HttpContext.Current.ApplicationInstance.CompleteRequest();
    }
    catch
    {
        // Handle potential IO or formatting errors
    }
    finally
    {
        GC.Collect();
    }
}

Tags: Excel Export Form Submission JSON Serialization C# File Download

Posted on Fri, 06 Nov 2026 16:08:37 +0000 by windwaker