3
我有一个尝试解决方案在渲染ActionResult
到字符串。我通过传递我自己的HttpContext
来完成这项工作,它将输出文本编写器替换为我自己的TextWriter
。渲染ActionResult字符串 - 出现在不正确的顺序
下面是问题 - 元素呈现乱序。如果我通过直接通过浏览器查询来渲染局部视图,它可以正常工作。如果我通过替代文本编写器来渲染它,则无论在视图中的位置如何,剃须刀视图中的任何@ Html.Action元素都将首先呈现。
所以,这里是我的Razor视图:
@inherits System.Web.Mvc.WebViewPage<WebsitePresentationLayer.MgrScreenLayoutViewer>
@using System.Web.Mvc.Html;
<div>
@Model.DebugText
</div>
@foreach (var item in @Model.Items)
{
<div>@item.Title</div>
@Html.Action(
"LayoutItem",
new
{
id = item.Id,
uniqueName = item.UniqueName
}
);
}
如果我直接通过浏览器查询视图,它呈现在正确的顺序:
- @ Model.DebugText
- 项目1。标题
- Item1动作渲染
- Item2.Title
- 项目2的描绘
如果我使这个对我的TextWriter,它呈现以下顺序:
- 项目1的描绘
- 项目2的描绘
- @ Model.DebugText
- Item1.Title
- Item2.Title
为什么?
下面是我如何使用文本编写器进行编程。
StringBuilder sb = new StringBuilder();
StringWriter stringWriter = new StringWriter(sb);
CMS.Website.MvcUtils.RenderControllerAction<PlayerGroupController>
(
c => c.ScreenLayout(this.MgrPlayerGroupViewer.ScreenLayoutId),
stringWriter
);
stringWriter.Flush();
var generatedString = sb.ToString();
:然后我终于将其输出到字符串使用下面的代码(我从ASP.NET Web窗体页面调用这个,所以已经有一个现有的
HttpContext
)
public static class ActionResultExtensions
{
internal class MyResponseWrapper : HttpResponseWrapper
{
private System.IO.TextWriter _textWriter;
public MyResponseWrapper(HttpResponse wrappedResponse, System.IO.TextWriter textWriter)
: base(wrappedResponse)
{
_textWriter = textWriter;
}
public override System.IO.TextWriter Output
{
get { return this._textWriter; }
set { this._textWriter = value; }
}
}
internal class MyHttpContextWrapper : HttpContextWrapper
{
private readonly System.IO.TextWriter _textWriter;
public MyHttpContextWrapper(System.IO.TextWriter textWriter)
: base(HttpContext.Current)
{
this._textWriter = textWriter;
}
public override HttpResponseBase Response
{
get
{
var httpResponse = HttpContext.Current.Response;
return new MyResponseWrapper(httpResponse, this._textWriter);
}
}
}
public static void Render(this System.Web.Mvc.ActionResult result, System.IO.TextWriter textWriter, System.Web.Routing.RouteData routeData, System.Web.Mvc.ControllerBase controllerBase)
{
var httpContextWrapper = new MyHttpContextWrapper(textWriter);
result.ExecuteResult(new System.Web.Mvc.ControllerContext(httpContextWrapper, routeData, controllerBase));
}
}
public static class MvcUtils
{
public static void RenderControllerAction<T>(Func<T, System.Web.Mvc.ActionResult> f, System.IO.TextWriter writer) where T : System.Web.Mvc.ControllerBase, new()
{
var controller = new T();
// We have to initialise the RouteData so that it knows the name of the controller
// This is used to locate the view
var typeName = controller.GetType().Name;
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex("(.*)Controller$");
var match = regex.Match(typeName);
if (match.Success)
{
typeName = match.Groups[1].Value;
}
var routeData = new System.Web.Routing.RouteData();
routeData.Values.Add("controller", typeName);
var actionResult = f(controller);
actionResult.Render(writer, routeData, controller);
}
}
而且 我写一个拦截器的TextWriter
,果然,它接收三个电话到Write(string)
- 写(LAYO utItem 1分的动作内容)
- 写(LayoutItem 2项行动内容)
- 写(Model.DebugText和两个项目冠军)
谢谢。我不得不手动创建我自己的ControllerContext,但这解决了我的特殊问题。我仍然希望弄清楚为什么ViewEngine在我调用ActionResult.ExecuteResult时以一种奇怪的顺序渲染。 – 2013-03-06 00:52:55
@AndrewShepherd我记得在这方面挣扎。起初,我只是试图返回一个部分,没有得到我想要的东西。我不得不通过控制器并通过它“处理”我的视图。一旦我决定了方向,一整天都会头朝天。你似乎在做类似的事情,但是来自一个稍微不同的方向。我必须再次深入了解它。 – 2013-03-06 01:34:31