2009-02-06 14 views
22

Me gustaría utilizar mi acción en asp.net mvc, como motor de plantilla, que da como resultado una cadena, que podría enviar por correo electrónico.Enviar el resultado de la acción asp.net mvc dentro del correo electrónico

pseudo-código:

public ActionResult Register() 
{ 
    SendEmail(View().ToString()); 

    return new EmptyResult(); 
} 
+0

¿Puede aclarar lo que quiere hacer? –

+0

con pseudo? ¿Está más claro? –

+0

Las solicitudes a un servidor web tienen que devolver * algo. * ¿Qué esperas que devuelva? HTML? JSON? ¿Algo más? ¿O preguntas cómo enviar un correo electrónico? No, aún no está claro. –

Respuesta

1

No se puede ver la vista en sí en el interior del controlador. La forma de hacer lo que pide es escribir una subclase ActionResult personalizada y un ViewEngine personalizado para manejarla. Anule ExecuteResult para enviar realmente el correo electrónico. Mire el código abierto Spark, NHAML, etc., vea los motores para MVC para ver ejemplos.

14

En primer lugar, es probable que desee devolver una vista de su acción, por lo que devolver un EmptyResult no es el mejor; pero lo sabrá cuando esté lidiando con el flujo de páginas en su proceso de registro.

Supongo que desea crear un correo electrónico HTML utilizando una Vista que ya ha creado. Eso significa que usted desea tomar el resultado de algo que se parece a lo siguiente:

public ActionResult CreateEmailView(RegistrationInformation info) 
{ 
    var userInformation = Membership.CreateNewUserLol(info); 
    return View(userInformation) 
} 

y enviar que a medida que el cuerpo del correo electrónico. Puedes volver a utilizar tus puntos de vista y todas esas cosas divertidas.

Puede aprovechar el marco creando un ActionResult personalizado y usándolo para generar su texto.

Aquí hay un pseudocódigo de tipo C# que en realidad podría compilar y funcionar. En primer lugar, la ActionResult personalizado:

public class StringResult : ViewResult 
{ 
    public string Html { get; set; } 
    public override void ExecuteResult(ControllerContext context) 
    { 
     if (context == null) 
     { 
      throw new ArgumentNullException("context"); 
     } 
     if (string.IsNullOrEmpty(this.ViewName)) 
     { 
      this.ViewName = 
       context.RouteData.GetRequiredString("action"); 
     } 
     ViewEngineResult result = null; 
     if (this.View == null) 
     { 
      result = this.FindView(context); 
      this.View = result.View; 
     } 
     ViewContext viewContext = new ViewContext(
       context, this.View, this.ViewData, this.TempData); 
     using (var stream = new MemoryStream()) 
     using (var writer = new StreamWriter(stream)) 
     { 
      // used to write to context.HttpContext.Response.Output 
      this.View.Render(viewContext, writer); 
      writer.Flush(); 
      Html = Encoding.UTF8.GetString(stream.ToArray()); 
     } 
     if (result != null) 
     { 
      result.ViewEngine.ReleaseView(context, this.View); 
     } 
    } 
} 

Esto anula el método de base ExecuteResult (este es el código del método de base que estoy anulando; puede haber cambiado en RC1) para rendir a un arroyo que yo controlo en lugar de la Flujo de salida de la respuesta. Por lo tanto, extrae el texto exactamente cómo se representaría en la máquina del cliente.

A continuación, como se puede utilizar esto en una acción de controlador:

public ActionResult CreateEmailView(RegistrationInformation info) 
{ 
    var userInformation = Membership.CreateNewUserLol(info); 
    // grab our normal view so we can get some info out of it 
    var resultView = View(userInformation); 

    // create our string result and configure it 
    StringResult sr = new StringResult(); 
    sr.ViewName = resultView.ViewName; 
    sr.MasterName = resultView.MasterName; 
    sr.ViewData = userInformation; 
    sr.TempData = resultView.TempData; 
    // let them eat cake 
    sr.ExecuteResult(this.ControllerContext); 
    string emailHtml = sr.Html; 
    // awesome utils package, dude 
    Utils.SendEmailKThx(userInformation, emailHtml); 

    return resultView; 
} 

Estoy prestando la misma vista en dos ocasiones; la primera vez que la renderizo en una secuencia y la segunda vez la renderizo normalmente. Es posible colarse en la cadena de llamadas de ViewResult en otro lugar y cambiar la forma en que Render opera, pero una mirada rápida al código no revela nada. Si bien el marco es bastante bueno, la pila de llamadas para partes del proceso no es lo suficientemente fina como para que sea fácil cambiar un solo paso en el proceso. Si rompieron ExecuteResult en unos pocos métodos reemplazables diferentes, podríamos haberlo cambiado de renderizado a flujo de salida para renderizar a nuestra corriente sin anular todo el método ExecuteResult. Oh, bueno ...

+0

Somewhy does not work for me. Html está vacío al final. :/ –

+0

Normalmente tiene que ver con la transmisión. Escribes el html en la transmisión, luego intentas transmitir esa transmisión a otra persona, probablemente no volverán al principio. Busca 0 y deberás encontrar tu HTML. – Will

+2

Holy crap .... MVC 1 ignora completamente la transmisión y solo escribe en la respuesta. http://ayende.com/Blog/archive/2008/11/11/another-asp.net-mvc-bug-rendering-views-to-different-output-source.aspx Me pregunto si han solucionado esto en 2 ? – Will

6

Here's cómo ver la vista como una cadena.

+0

¡esta es una pregunta realmente confusa! ¡Creo que para la mayoría de las personas que terminan aquí esto es lo que están realmente necesitando! esta pregunta es, de hecho, incluso más específica sobre cómo obtener la vista PARA un correo electrónico dentro de otro controlador –

0

Hola, por lo que estoy leyendo (y mi propio intento de implementar su solución) el método View.Render ignora por completo el parámetro del escritor. El contenido de mi escritor siempre está vacío y, en cambio, la vista representada se deja escapar en la secuencia de respuesta. Por lo tanto, parece imposible (o al menos intrincado al menos) para obtener su uso que ve de esa manera.Creo que en su caso de prueba verá la vista renderizada dos veces y su correo electrónico estará en blanco.

me encontré con una cierta discusión sobre esto aquí: http://ayende.com/Blog/archive/2008/11/11/another-asp.net-mvc-bug-rendering-views-to-different-output-source.aspx

5

http://www.brightmix.com/blog/renderpartial-to-string-in-asp-net-mvc/ tiene una buena solución para la representación de una vista a una cadena para que pueda enviarlo por correo electrónico. Señala que "al hacer una vista parcial de la cuerda, afortunadamente, se ha vuelto mucho, mucho más fácil".

/// Static Method to render string - put somewhere of your choosing 
public static string RenderPartialToString(string controlName, object viewData) 
{ 
    ViewDataDictionary vd = new ViewDataDictionary(viewData); 
    ViewPage vp = new ViewPage { ViewData = vd }; 
    Control control = vp.LoadControl(controlName); 

    vp.Controls.Add(control); 

    StringBuilder sb = new StringBuilder(); 
    using (StringWriter sw = new StringWriter(sb)) 
    { 
     using (HtmlTextWriter tw = new HtmlTextWriter(sw)) 
     { 
      vp.RenderControl(tw); 
     } 
    } 

    return sb.ToString(); 
} 
1

En este artículo se proporcionan la mejor respuesta para mí:

Render any ASP.NET MVC ActionResult to a string

+0

¿Cómo no se sube más la respuesta? Es de lejos el más rápido, el más simple y cubre la pregunta del OP de manera más completa en comparación con muchas de las otras respuestas más votadas. –

Cuestiones relacionadas