在电子邮件中发送asp.net mvc动作结果

app*_*orm 22 asp.net-mvc template-engine

我想在asp.net mvc中使用我的Action作为模板引擎,它会产生字符串形式,我可以通过电子邮件发送.

伪代码:

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

    return new EmptyResult();
}
Run Code Online (Sandbox Code Playgroud)

小智 13

首先,你仍然可能想要从你的动作返回一个视图,所以返回一个EmptyResult不是最好的; 但是当你在注册过程中处理页面流时,你会发现这一点.

我假设您希望使用您已创建的视图创建HTML电子邮件.这意味着您希望获得类似于以下内容的结果:

public ActionResult CreateEmailView(RegistrationInformation info)
{
  var userInformation = Membership.CreateNewUserLol(info);
  return View(userInformation)
}
Run Code Online (Sandbox Code Playgroud)

并将其作为电子邮件的正文发送.您可以重用您的视图和所有有趣的东西.

您可以通过创建自定义ActionResult并使用它来生成文本来利用该框架.

这是一些可能实际编译和工作的类似c#的伪代码.首先,自定义ActionResult:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这将覆盖基本方法的ExecuteResult(这是我覆盖的基本方法中的代码;可能在RC1中已更改)以呈现为我控制的流而不是Response的输出流.因此,它会准确地提取文本如何呈现给客户端计算机.

接下来,如何在控制器操作中使用它:

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;
}
Run Code Online (Sandbox Code Playgroud)

我两次渲染相同的视图; 我第一次将它渲染到流中,第二次我正常渲染它.有可能潜入其他地方的ViewResult调用链并改变Render的操作方式,但粗略地看一眼代码并没有透露任何东西.虽然框架非常好,但部分流程的调用堆栈不够精细,无法轻松更改流程中的单个步骤.如果他们将ExecuteResult分解为几个不同的可覆盖方法,我们可以将它从渲染更改为输出流,以渲染到我们的流,而不会覆盖整个ExecuteResult方法.那好吧....

  • 神圣的废话.... MVC 1完全忽略了流,只是写入响应.http://ayende.com/Blog/archive/2008/11/11/another-asp.net-mvc-bug-rendering-views-to-different-output-source.aspx我想知道他们是否已修复此问题2 ? (2认同)

Jon*_*han 6

我没有足够的评论来评论,但我想我会节省一些时间,指出似乎接受的答案会起作用,如果它确实会很好.但是,似乎WebForm视图引擎只是吃了TextWriter参数.这里有更多信息:http://ayende.com/Blog/archive/2008/11/11/another-asp.net-mvc-bug-rendering-views-to-different-output-source.aspx


Ian*_*cer 5

http://www.brightmix.com/blog/renderpartial-to-string-in-asp-net-mvc/有一个很好的解决方案,可以将View渲染为字符串,以便您可以通过电子邮件发送它.他指出"幸运的是,渲染部分视图到字符串变得更容易了."

/// 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();
}
Run Code Online (Sandbox Code Playgroud)


Cra*_*ntz 1

您无法在控制器内部看到视图本身。执行您要求的操作的方法是编写一个自定义 ActionResult 子类,以及一个自定义 ViewEngine 来处理它。重写 ExecuteResult 以实际发送电子邮件。看看开源的Spark、NHAML等,MVC的视图引擎为例。