Razor view - испускает html вне тега Doctype - PullRequest
3 голосов
/ 15 июля 2011

Я пытаюсь написать модуль / области на основе mvc3 CMS, используя бритвенный движок. У меня есть два представления макета, _site.cshtml и _modules.cshtml. В _site.cshtml есть раздел @RenderBody (). Мое приложение всегда вызывает представление с именем «index.cshtml», в макете которого задана страница _site.cshtml. Проблема: Проблема в том, что мои модули / области отображаются перед элементом doctype, а не внутри раздела RenderBody страницы макета.

Ответы [ 3 ]

2 голосов
/ 17 июля 2011

Похоже, что вы пытаетесь сделать, это эквивалент Html.RenderAction (или Html.Action), так почему вы пишете весь этот код самостоятельно, а не используете встроенную функциональность?

1 голос
/ 16 июля 2011

Короче говоря, это ваш метод 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();
}

Приведенный выше код генерирует новый запрос и возвращает HTML-код запроса в виде строки.Таким образом, результат добавляется как часть текущего ответа.Теперь вы можете переписать функцию Invoke (), чтобы вернуть строку, которая может отображаться в вашем представлении.

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, я не смог протестировать этот код специально для вашего сценария.Вместо этого я воспроизвел проблему как можно лучше и решил ее.

Пожалуйста, дайте мне знать, если у вас есть какие-либо вопросы.

Matt

0 голосов
/ 18 июля 2011

Позвольте мне опубликовать правдоподобную вторую альтернативу вашим методам, пока я пытаюсь решить вышеуказанную проблему.

В MVC есть расширение html под названием Html.Partial (), которое позволяет вам использовать routedata для возвратарезультат действия контроллера.

Итак, если у вас есть AccountController с методом Register, который возвращает результат PartialView, он будет добавлен к текущей странице.

public class AccountController() : Controller
{
  public ActionResult Register()
  {
    return PartialView();
  }
}

призыв к этому действию может выглядеть примерно так:

@Html.Partial("Account", "Register");

|- Примечание - |

Не используйте @ Html.RenderPartial (), иначе у вас будет та же проблема, что и выше!В настоящее время я публикую сообщения вне компьютера, поэтому я не могу проверить эту теорию!

Надеюсь, это поможет!

Мэтт

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...