Quero gerar duas visualizações diferentes (uma como uma sequência que será enviada como um email) e a outra a página exibida para um usuário.
Isso é possível no ASP.NET MVC beta?
Eu tentei vários exemplos:
1. RenderPartial to String no ASP.NET MVC Beta
Se eu usar este exemplo, recebo a mensagem "Não é possível redirecionar após o envio dos cabeçalhos HTTP".
2. MVC Framework: Capturando a Saída de uma Visualização
Se eu usar isso, parece que não consigo fazer um redirectToAction, pois ele tenta renderizar uma exibição que pode não existir. Se eu retornar a exibição, ela estará completamente bagunçada e não parecerá correta.
Alguém tem alguma idéia / solução para esses problemas que tenho, ou tem alguma sugestão para outras melhores?
Muito Obrigado!
Abaixo está um exemplo. O que estou tentando fazer é criar o método GetViewForEmail :
public ActionResult OrderResult(string ref)
{
//Get the order
Order order = OrderService.GetOrder(ref);
//The email helper would do the meat and veg by getting the view as a string
//Pass the control name (OrderResultEmail) and the model (order)
string emailView = GetViewForEmail("OrderResultEmail", order);
//Email the order out
EmailHelper(order, emailView);
return View("OrderResult", order);
}
Resposta aceita de Tim Scott (alterada e formatada um pouco por mim):
public virtual string RenderViewToString(
ControllerContext controllerContext,
string viewPath,
string masterPath,
ViewDataDictionary viewData,
TempDataDictionary tempData)
{
Stream filter = null;
ViewPage viewPage = new ViewPage();
//Right, create our view
viewPage.ViewContext = new ViewContext(controllerContext, new WebFormView(viewPath, masterPath), viewData, tempData);
//Get the response context, flush it and get the response filter.
var response = viewPage.ViewContext.HttpContext.Response;
response.Flush();
var oldFilter = response.Filter;
try
{
//Put a new filter into the response
filter = new MemoryStream();
response.Filter = filter;
//Now render the view into the memorystream and flush the response
viewPage.ViewContext.View.Render(viewPage.ViewContext, viewPage.ViewContext.HttpContext.Response.Output);
response.Flush();
//Now read the rendered view.
filter.Position = 0;
var reader = new StreamReader(filter, response.ContentEncoding);
return reader.ReadToEnd();
}
finally
{
//Clean up.
if (filter != null)
{
filter.Dispose();
}
//Now replace the response filter
response.Filter = oldFilter;
}
}
Exemplo de uso
Supondo uma chamada do controlador para obter o email de confirmação do pedido, passando o local Site.Master.
string myString = RenderViewToString(this.ControllerContext, "~/Views/Order/OrderResultEmail.aspx", "~/Views/Shared/Site.Master", this.ViewData, this.TempData);
fonte
Respostas:
Aqui está o que eu criei e está funcionando para mim. Adicionei o (s) seguinte (s) método (s) à minha classe base do controlador. (Você sempre pode criar esses métodos estáticos em outro lugar que aceite um controlador como parâmetro, suponho)
Estilo MVC2 .ascx
Estilo .cshtml do Razor
Edit: adicionado código Razor.
fonte
Esta resposta não está a caminho. Isso é originalmente de https://stackoverflow.com/a/2759898/2318354, mas aqui eu mostrei a maneira de usá-lo com a palavra-chave "Static" para torná-lo comum a todos os controladores.
Para isso você tem que criar
static
classe no arquivo de classe. (Suponha que seu nome de arquivo de classe seja Utils.cs)Este exemplo é For Razor.
Utils.cs
Agora você pode chamar essa classe do seu controlador adicionando NameSpace no arquivo do controlador da seguinte maneira, passando "this" como parâmetro para o Controller.
Como sugestão dada pelo @Sergey, esse método de extensão também pode chamar do cotroller, conforme mostrado abaixo
Espero que isso seja útil para você tornar o código limpo e arrumado.
fonte
Isso funciona para mim:
fonte
Encontrei uma nova solução que renderiza uma exibição de string sem ter que mexer com o fluxo de resposta do HttpContext atual (que não permite alterar o ContentType da resposta ou outros cabeçalhos).
Basicamente, tudo o que você faz é criar um HttpContext falso para que a exibição seja renderizada:
Isso funciona no ASP.NET MVC 1.0, junto com ContentResult, JsonResult, etc. (alterar os cabeçalhos no HttpResponse original não gera a exceção "O servidor não pode definir o tipo de conteúdo após o envio dos cabeçalhos HTTP ").
Atualização: no ASP.NET MVC 2.0 RC, o código muda um pouco porque precisamos passar o
StringWriter
usado para gravar a exibição noViewContext
:fonte
StringWriter
que está usando para gravar naStringBuilder
, não uma nova instância ou a saída da exibição será perdida.Este artigo descreve como renderizar uma exibição em uma seqüência de caracteres em diferentes cenários:
A solução / código é fornecida como uma classe chamada ViewRenderer . Faz parte do WestwindToolkit de Rick Stahl no GitHub .
Uso (3. - exemplo de WebAPI):
fonte
Se você deseja renunciar inteiramente ao MVC, evitando assim toda a bagunça HttpContext ...
Ele usa o incrível Razor Engine de código aberto aqui: https://github.com/Antaris/RazorEngine
fonte
CompilerErrors
propriedade da exceção.você obtém a visão em string usando este caminho
Nós chamamos esse método de duas maneiras
OU
fonte
Dica adicional para o ASP NET CORE:
Interface:
Implementação:
Registro em
Startup.cs
E uso no controlador:
fonte
Estou usando o MVC 1.0 RTM e nenhuma das soluções acima funcionou para mim. Mas este fez:
fonte
Vi uma implementação do MVC 3 e Razor de outro site, funcionou para mim:
Mais sobre Razor render- MVC3 View Render to String
fonte
Para renderizar uma exibição em uma seqüência de caracteres na Camada de serviço sem precisar passar o ControllerContext, há um bom artigo de Rick Strahl aqui http://www.codemag.com/Article/1312081 que cria um controlador genérico. Resumo do código abaixo:
Em seguida, para renderizar a exibição na classe de serviço:
fonte
Dica rápida
Para um modelo fortemente tipado, adicione-o à propriedade ViewData.Model antes de passar para RenderViewToString. por exemplo
fonte
Para repetir a partir de uma pergunta mais desconhecida, consulte MvcIntegrationTestFramework .
Isso economiza a você escrever seus próprios auxiliares para transmitir resultados e está comprovado que funciona bem o suficiente. Eu diria que isso seria em um projeto de teste e, como bônus, você teria os outros recursos de teste assim que tiver essa configuração. O incômodo principal provavelmente estaria resolvendo a cadeia de dependência.
fonte
Aqui está uma classe que escrevi para fazer isso no ASP.NETCore RC2. Eu o uso para que eu possa gerar emails em html usando o Razor.
fonte
Encontrei uma maneira melhor de renderizar a página de exibição do razor quando recebi um erro com os métodos acima, esta solução para o ambiente de formulário da web e o ambiente de mvc. Nenhum controlador é necessário.
Aqui está o exemplo de código, neste exemplo eu simulei uma ação mvc com um manipulador http assíncrono:
fonte