【问题标题】:ASP MVC - Manually execute child actionASP MVC - 手动执行子动作
【发布时间】:2016-06-27 17:11:34
【问题描述】:

我正在为 ASP.NET MVC 编写自定义视图引擎。我正在尝试添加对子操作的支持。下面是应该执行子操作并将结果作为字符串返回的处理程序。到目前为止一切正常;该方法在应该调用的时候被调用,并且所有参数都正确填充。

private string HandleActionHelper(ViewContext viewContext, string actionName, string controllerName, RouteValueDictionary routeValues)
    {
        var routeData = new RouteData();

        if (string.IsNullOrEmpty(controllerName))
            controllerName = viewContext.RouteData.Values["controller"] as string;

        routeData.Values["action"] = actionName;
        routeData.Values["controller"] = controllerName;
        foreach(var value in routeValues)
        {
            routeData.Values.Add(value.Key, value.Value);
        }

        var requestContext = new RequestContext(viewContext.HttpContext, routeData);
        var mvcHandler = new MvcHandler(requestContext);

        StringWriter writer = new StringWriter();
        viewContext.HttpContext.Server.Execute(mvcHandler, writer, true);

        return writer.GetStringBuilder().ToString();
    }

它在viewContext.HttpContext.Server.Execute(mvcHandler, writer, true); 上抛出一个System.Web.HttpException

完整的错误信息如下:

执行处理程序“System.Web.Mvc.MvcHandler”的子请求时出错。

我一直在网上搜索并查看 MVC 资源以了解如何使用,这是我最好的尝试,而无需复制/粘贴大量 internal MVC 类。

如何执行子操作并将结果作为字符串返回?

编辑:添加完整的堆栈跟踪

System.Web.dll!System.Web.HttpServerUtility.ExecuteInternal(System.Web.IHttpHandler 处理程序,System.IO.TextWriter writer,bool preserveForm,bool setPreviousPage, System.Web.VirtualPath 路径, System.Web.VirtualPath filePath,字符串 physPath,System.Exception 错误,字符串 queryStringOverride) 未知 System.Web.dll!System.Web.HttpServerUtility.Execute(System.Web.IHttpHandler 处理程序,System.IO.TextWriter writer,bool preserveForm,bool setPreviousPage) 未知 System.Web.dll!System.Web.HttpServerUtility.Execute(System.Web.IHttpHandler 处理程序,System.IO.TextWriter writer,bool preserveForm)未知 System.Web.dll!System.Web.HttpServerUtilityWrapper.Execute(System.Web.IHttpHandler 处理程序,System.IO.TextWriter writer,bool preserveForm)未知 JadeViewEngine.dll!JadeViewEngine.JadeView.HandleActionHelper(System.Web.Mvc.ViewContext viewContext,字符串 actionName,字符串 controllerName, System.Web.Routing.RouteValueDictionary routeValues) 第 85 行 C# JadeViewEngine.dll!JadeViewEngine.JadeView.Render.AnonymousMethod__0(动态 输入)第 39 行 C# edge_nativeclr.node!ClrFunc.Call(value, payload, 回调)未知 edge_nativeclr.node!.clrFuncProxy(Nan.FunctionCallbackInfo* info) 未知 [本地到托管转换] [托管到本地 过渡]
edge_nativeclr.node!.Nan.imp.?A0x8dda69af.FunctionCallbackWrapper(v8.FunctionCallbackInfo* info) 未知 [本地到托管转换] [托管到本地 过渡]
edge_nativeclr.node!NodejsFuncInvokeContext.CallFuncOnV8Thread() 未知 edge_nativeclr.node!.clrActionContext.ActionCallback(void* 数据)未知 [本机到托管转换] [托管到本机 过渡]
edge_nativeclr.node!.continueOnV8Thread(uv_async_s* 句柄, int status) 未知 [本地到托管转换] [托管到本地 过渡] EdgeJs.dll!EdgeJs.Edge.Func.AnonymousMethod__1() 未知 mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(对象 状态)未知 mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext、System.Threading.ContextCallback 回调、对象 state, bool preserveSyncCtx) 未知 mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext、System.Threading.ContextCallback 回调、对象 state, bool preserveSyncCtx) 未知 mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext、System.Threading.ContextCallback 回调、对象 状态)未知 mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() 未知 [本机到托管转换]

【问题讨论】:

  • 什么是完整的堆栈跟踪?我不确定这是正确的方法 - 子操作通常通过在同一响应流上触发子请求来工作,而不是通过写入字符串。
  • @AntP 堆栈跟踪已添加到问题中。如果你在 Razor 视图中调用 HtmlHelper.RenderAction(),它会写入流,但如果你调用`HtmlHelper.Action()`,它会返回一个 MvcString,然后你可以调用 ToString()
  • 自发布此问题以来,我一直试图通过创建HtmlHelper 的实例并使用其Action() 方法来完成此操作。这完全符合我在测试中的要求。问题是我正在使用 Edge.js 执行一些 NodeJS 代码,如果我在我的 HandleActionHelper() 方法(它本身由 NodeJS 代码调用)中调用 HtmlHelper.Action(),那么 Action() 方法永远不会返回并且有没有错误或异常。我认为解决这个问题将是这个问题的主题。我仍然想知道是否有更合适的方法来做我想做的事情。

标签: asp.net-mvc asp.net-mvc-5


【解决方案1】:

所以我对此的解决方案是创建您在 Razor 视图中获得的 HtmlHelper 类的实例,然后使用其 Action() 方法获取结果字符串:

using System.Web.Mvc; // Bring in HtmlHelper
using System.Web.Mvc.Html; // Bring in HtmlHelper's extension methods.
...
var html = new HtmlHelper(viewContext, new ViewPage());
string actionResults = html.Action("ActionName", "ControllerName");

注意 1:这是在自定义视图引擎的自定义 IView 实现中,所以我只是传入了我已经拥有的 ViewContext 实例。如果您没有可用的ViewContext,则必须创建一个。这是一个旧示例(因此不确定它的效果如何),但它应该可以帮助您入门:Create HtmlHelper instance in Controller

注意 2: 正如我最初问题的 cmets 中所述,我在使用这种方法时遇到了问题。据我所知,HtmlHelper 在异步上下文中无法正常工作。我使用 Edge.js 调用 NodeJS 代码,这都是异步的东西,所以我认为这是造成这些问题的原因。当我将调用移至 Edge.js 之外的 HtmlHelper 时,它运行良好。

【讨论】:

    猜你喜欢
    • 2012-04-19
    • 1970-01-01
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多