You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何生成并返回数据库中存储的CSHTML视图?模型绑定及方案咨询

Custom HTML Helper Approach

Absolutely, a custom HTML helper is a perfect fit for this scenario—it lets you encapsulate the logic of fetching the DB-stored CSHTML, compiling it, and binding your model directly within your views. Here's a step-by-step implementation:

Step 1: Create the Helper Class

First, build a static extension class for HtmlHelper that handles fetching the template from your database and rendering it with your model:

using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using RazorEngineCore;

namespace YourAppNamespace.Helpers
{
    public static class DynamicReportHelper
    {
        public static IHtmlString RenderDynamicReport(this HtmlHelper htmlHelper, string reportType, string userLocation, object model)
        {
            // 1. Fetch CSHTML from your database (replace with your stored procedure call)
            string cshtmlTemplate = FetchTemplateFromDb(reportType, userLocation);

            if (string.IsNullOrWhiteSpace(cshtmlTemplate))
            {
                return new HtmlString("No report template available for this location/report type.");
            }

            // 2. Compile and render the Razor template with your model
            var razorEngine = htmlHelper.ViewContext.HttpContext.RequestServices.GetRequiredService<IRazorEngine>();
            var compiledTemplate = razorEngine.Compile(cshtmlTemplate);
            var renderedHtml = compiledTemplate.Run(new ExecuteContext { Model = model });

            return new HtmlString(renderedHtml);
        }

        // Replace this with your actual stored procedure logic (use Dapper/EF Core here)
        private static string FetchTemplateFromDb(string reportType, string userLocation)
        {
            // Example: Return a sample CSHTML template tied to the report/location
            return @"
                <div class=""report-container"">
                    <h2>@Model.ReportName</h2>
                    <p>Generated for location: @ViewBag.UserLocation</p>
                    <table class=""table"">
                        <thead>
                            <tr>
                                <th>ID</th>
                                <th>Value</th>
                            </tr>
                        </thead>
                        <tbody>
                            @foreach(var item in Model.DataItems)
                            {
                                <tr>
                                    <td>@item.Id</td>
                                    <td>@item.Value</td>
                                </tr>
                            }
                        </tbody>
                    </table>
                </div>";
        }
    }
}

Step 2: Use the Helper in Your View

In your CSHTML view, reference the helper and pass in your parameters/model:

@model YourAppNamespace.Models.ReportModel
@using YourAppNamespace.Helpers

@{
    ViewBag.UserLocation = User.Claims.First(c => c.Type == "Location").Value;
}

@Html.RenderDynamicReport("SalesSummary", ViewBag.UserLocation, Model)

Alternative Implementation Options

1. Custom IView for Controller-Side Rendering

If you prefer handling the dynamic view logic at the controller level, you can create a custom IView that loads content from the database:

using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using RazorEngineCore;
using System.IO;

namespace YourAppNamespace.Views
{
    public class DatabaseView : IView
    {
        private readonly string _cshtmlContent;
        public string Path => "DynamicDatabaseView";

        public DatabaseView(string cshtmlContent)
        {
            _cshtmlContent = cshtmlContent;
        }

        public async Task RenderAsync(ViewContext context)
        {
            var razorEngine = context.HttpContext.RequestServices.GetRequiredService<IRazorEngine>();
            var compiledTemplate = razorEngine.Compile(_cshtmlContent);
            var renderedHtml = compiledTemplate.Run(new ExecuteContext 
            { 
                Model = context.ViewData.Model,
                ViewBag = context.ViewBag
            });

            await context.Writer.WriteAsync(renderedHtml);
        }
    }
}

Then use it in your controller:

public async Task<IActionResult> GenerateReport(string reportType)
{
    var userLocation = User.Claims.First(c => c.Type == "Location").Value;
    var cshtmlTemplate = FetchTemplateFromDb(reportType, userLocation);
    var reportModel = GetReportModel(reportType, userLocation); // Your model fetch logic

    return View(new DatabaseView(cshtmlTemplate), reportModel);
}

2. View Component for Modular Reuse

For more modularity, wrap the logic in a View Component—this is great if you need to reuse the dynamic report rendering across multiple views:

using Microsoft.AspNetCore.Mvc;
using RazorEngineCore;

namespace YourAppNamespace.ViewComponents
{
    public class DynamicReportViewComponent : ViewComponent
    {
        private readonly IRazorEngine _razorEngine;

        public DynamicReportViewComponent(IRazorEngine razorEngine)
        {
            _razorEngine = razorEngine;
        }

        public async Task<IViewComponentResult> InvokeAsync(string reportType, string userLocation, object model)
        {
            string cshtmlTemplate = FetchTemplateFromDb(reportType, userLocation);
            var renderedHtml = _razorEngine.Compile(cshtmlTemplate).Run(new ExecuteContext { Model = model });
            
            return Content(renderedHtml);
        }

        private string FetchTemplateFromDb(string reportType, string userLocation)
        {
            // Your stored procedure call here
            return "";
        }
    }
}

Call it in your view like this:

@model YourAppNamespace.Models.ReportModel

<vc:dynamic-report report-type="Inventory" user-location="@User.Claims.First(c => c.Type == ""Location"").Value" model="@Model" />

Key Considerations

  • Security: Since you're executing raw CSHTML from the database, restrict access to template editing to trusted users only—malicious code in the template could execute on your server.
  • Caching: Add caching (e.g., IMemoryCache) for frequently used templates to avoid repeated database calls and compilation overhead.
  • Type Safety: Ensure your DB templates reference the correct model type—store the model's fully qualified name alongside the template in the database to validate during rendering.

内容的提问来源于stack exchange,提问作者Mahesh Kudikala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:13:01