Razor视图 - 在Doctype标签外发出html

时间:2011-07-15 17:52:16

标签: asp.net html asp.net-mvc-3 razor

我正在尝试使用剃刀视图引擎编写基于模块/区域的mvc3 CMS。我有两个布局视图,_site.cshtml和_modules.cshtml。 _site.cshtml有一个@RenderBody()部分。我的应用程序总是调用一个名为“index.cshtml”的视图,其布局设置为_site.cshtml页面。 问题:问题是我的模块/区域在doctype元素之前呈现 - 而不是在布局页面的RenderBody部分内。

3 个答案:

答案 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(),否则您将遇到与上述相同的问题! 我目前正在远离电脑,所以我无法测试这个理论!

希望这有帮助!

马特