我正在尝试使用剃刀视图引擎编写基于模块/区域的mvc3 CMS。我有两个布局视图,_site.cshtml和_modules.cshtml。 _site.cshtml有一个@RenderBody()部分。我的应用程序总是调用一个名为“index.cshtml”的视图,其布局设置为_site.cshtml页面。 问题:问题是我的模块/区域在doctype元素之前呈现 - 而不是在布局页面的RenderBody部分内。
答案 0 :(得分:2)
看起来你要做的就是Html.RenderAction(或Html.Action),你为什么要自己编写所有代码而不是使用内置功能呢?
答案 1 :(得分:1)
简而言之,它是你的Invoke()方法!剃刀引擎通过写入内存流,然后将其解析为响应来工作。您获得该行为的原因是因为您的Invoke()方法直接写入响应流;即在解析内存流之前。
我在使用Html.RenderAction()时遇到了类似的行为,它指向返回PartialView的操作。解决方法是使用Html.Action()。不同之处在于Action()返回一个附加到内存流中的字符串,RenderAction()直接写入响应。
如果您发布Invoke()方法的代码,我可以帮助您进一步!
| - 编辑 - |
好的,事实证明这最初预期会更复杂。问题是我无法将ProcessRequest()附加到当前响应;但是,我可能有一个解决方案。
public string ProcessRoute(ViewContext viewContext, RouteData routeData)
{
var urlHelper = new UrlHelper(viewContext.RequestContext);
var currentUrl = urlHelper.Action(routeData.Values["action"].ToString(),
routeData.Values["controller"].ToString(), routeData.DataTokens);
var stringWriter = new StringWriter();
var simpleWorkerRequest = new SimpleWorkerRequest(currentUrl, "", stringWriter);
var context = new HttpContext(simpleWorkerRequest);
var contextBase = new HttpContextWrapper(context);
var requestContext = new RequestContext(contextBase, routeData);
var httpHandler = routeData.RouteHandler.GetHttpHandler(requestContext);
httpHandler.ProcessRequest(context);
context.Response.End();
stringWriter.Flush();
return stringWriter.GetStringBuilder().ToString();
}
上面的代码生成一个新的Request并将Request的HTML作为字符串返回。通过这样做,结果作为当前响应的一部分附加。您现在可以重写Invoke()函数以返回一个字符串,该字符串可以显示在View上。
public string Invoke(ViewContext viewContext)
{
if (_mvcHandler == null)
{
var routeData = new RouteData(context.RouteData.Route,
context.RouteData.RouteHandler);
routeData.Values.Add("id", _id);
routeData.Values.Add("moduleName", _moduleName);
routeData.Values.Add("controller", _controllerName);
routeData.Values.Add("action", _actionName);
routeData.Values.Add("pageContext", _pageContext);
if (!string.IsNullOrEmpty(_preferredNamespace))
{
routeData.DataTokens.Add("Namespaces", new[] { _preferredNamespace });
}
return ProcessRoute(viewContext, routeData);
}
return string.Empty;
}
您可能还需要改变;
mr.Invoke(ViewContext);
要;
Html.Raw(mr.Invoke(ViewContext));
为了停止HTML编码行为。
| - 注意 - |
由于我没有您的ModuleRequests类,因此我无法专门针对您的方案测试此代码。相反,我尽我所能地复制了这个问题并解决了它。
如果您有任何疑问,请与我们联系。
马特
答案 2 :(得分:0)
在我尝试解决上述问题时,让我发布一个合理的第二种替代方法。
MVC中有一个名为Html.Partial()的html扩展,它允许您使用routedata返回控制器操作的结果。
因此,如果你有一个带有Register方法的AccountController返回一个PartialView结果,那么它将被附加到当前页面。
public class AccountController() : Controller
{
public ActionResult Register()
{
return PartialView();
}
}
对此操作的调用可能类似于;
@Html.Partial("Account", "Register");
| - 注意 - |
不要使用@ Html.RenderPartial(),否则您将遇到与上述相同的问题! 我目前正在远离电脑,所以我无法测试这个理论!
希望这有帮助!
马特