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

如何在ASP.NET Core服务中返回PartialView与JSON数据?

核心结论

你无法直接在服务层返回PartialView,因为服务层没有访问ASP.NET Core视图渲染所需的ViewContext、IViewEngine等上下文与服务组件,只有控制器(继承Controller/ControllerBase)才能处理视图相关操作。以下是两种可行的解决方案:


方案一:服务层返回业务数据,控制器负责视图渲染与响应组装(推荐)

此方案符合MVC分层设计原则,服务层专注业务逻辑,控制器处理视图渲染和JSON响应组装。

步骤1:调整服务层的响应结构

服务层不再直接返回HTML,而是返回业务模型或错误信息:

public class ServiceResponse
{
    // 传递给PartialView的视图模型
    public object ViewModel { get; set; }
    public bool IsSuccessful { get; set; }
    public Crud Mode { get; set; }
    // 失败时的错误信息
    public string ErrorMessage { get; set; }
}

public enum Crud { Create, Review, Update, Delete }

// 服务层方法
public ServiceResponse AddNew()
{
    try
    {
        var newEntity = new YourEntity(); // 构造业务实体
        _dbContext.Add(newEntity);
        _dbContext.SaveChanges();
        
        return new ServiceResponse
        {
            ViewModel = newEntity,
            IsSuccessful = true,
            Mode = Crud.Create
        };
    }
    catch (Exception ex)
    {
        return new ServiceResponse
        {
            IsSuccessful = false,
            Mode = Crud.Create,
            ErrorMessage = $"新增失败:{ex.Message}"
        };
    }
}

步骤2:控制器实现视图渲染与响应组装

在控制器中添加辅助方法将PartialView转为字符串,再组装成你需要的JSON格式:

public class YourController : Controller
{
    private readonly IYourService _myService;

    public YourController(IYourService myService)
    {
        _myService = myService;
    }

    // 辅助方法:将PartialView渲染为HTML字符串
    private async Task<string> RenderPartialViewToString(string viewName, object model)
    {
        ViewData.Model = model;

        using (var writer = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
            var viewContext = new ViewContext(
                ControllerContext, 
                viewResult.View, 
                ViewData, 
                TempData, 
                writer, 
                new HtmlHelperOptions()
            );
            
            await viewResult.View.RenderAsync(viewContext);
            return writer.GetStringBuilder().ToString();
        }
    }

    public async Task<IActionResult> Manage()
    {
        var serviceResponse = _myService.AddNew();
        string htmlContent;

        if (serviceResponse.IsSuccessful)
        {
            // 渲染成功状态的PartialView(例如"_TableRowPartial")
            htmlContent = await RenderPartialViewToString("_TableRowPartial", serviceResponse.ViewModel);
        }
        else
        {
            // 渲染错误提示的HTML,或直接使用错误信息生成HTML
            htmlContent = $"<h1>{serviceResponse.ErrorMessage}</h1>";
        }

        // 返回符合前端预期的JSON响应
        return Json(new 
        {
            htmlContent = htmlContent,
            mode = serviceResponse.Mode.ToString().ToLower(),
            isSuccessful = serviceResponse.IsSuccessful
        });
    }
}

方案二:服务层注入视图依赖(不推荐)

若因特殊需求必须在服务层处理视图渲染,可注入IViewEngine和ITempDataProvider,并由控制器传递ControllerContext。此方案会破坏分层设计,增加耦合度,仅建议在特殊场景使用。

步骤1:服务层注入视图相关服务

public class YourService
{
    private readonly DbContext _dbContext;
    private readonly IViewEngine _viewEngine;
    private readonly ITempDataProvider _tempDataProvider;

    public YourService(DbContext dbContext, IViewEngine viewEngine, ITempDataProvider tempDataProvider)
    {
        _dbContext = dbContext;
        _viewEngine = viewEngine;
        _tempDataProvider = tempDataProvider;
    }

    public async Task<Response> AddNew(ControllerContext controllerContext)
    {
        try
        {
            var newEntity = new YourEntity();
            _dbContext.Add(newEntity);
            _dbContext.SaveChanges();

            // 渲染PartialView为HTML字符串
            string htmlContent;
            using (var writer = new StringWriter())
            {
                var viewResult = _viewEngine.FindPartialView(controllerContext, "_TableRowPartial");
                var viewContext = new ViewContext(
                    controllerContext,
                    viewResult.View,
                    new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
                    {
                        Model = newEntity
                    },
                    new TempDataDictionary(controllerContext.HttpContext, _tempDataProvider),
                    writer,
                    new HtmlHelperOptions()
                );

                await viewResult.View.RenderAsync(viewContext);
                htmlContent = writer.GetStringBuilder().ToString();
            }

            return new Response
            {
                HtmlContent = htmlContent,
                IsSuccessful = true,
                Mode = Crud.Create
            };
        }
        catch
        {
            return new Response
            {
                HtmlContent = "<h1>something went wrong !</h1>",
                IsSuccessful = false,
                Mode = Crud.Create
            };
        }
    }

    public class Response
    {
        public string HtmlContent { get; set; }
        public bool IsSuccessful { get; set; }
        public Crud Mode { get; set; }
    }

    public enum Crud { Create, Review, Update, Delete }
}

步骤2:控制器传递上下文并返回响应

public async Task<IActionResult> Manage()
{
    var response = await _myService.AddNew(ControllerContext);
    return Json(new 
    {
        htmlContent = response.HtmlContent,
        mode = response.Mode.ToString().ToLower(),
        isSuccessful = response.IsSuccessful
    });
}

内容的提问来源于stack exchange,提问作者Mohamed Abuelatta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 20:50:31