Отправить asp.net результат действия MVC внутри электронной почты

Я хотел бы использовать мой Action в asp.net mvc, как шаблонизатор, который приводит к форме строки, которую я мог бы отправить по электронной почте.

Псевдо-код:

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

    return new EmptyResult();
}

9 ответов

Во-первых, вы все равно, вероятно, захотите вернуть представление из своего действия, поэтому возвращение EmptyResult не является лучшим; но вы поймете это, когда будете иметь дело с потоком страниц в процессе регистрации.

Я предполагаю, что вы хотите создать электронное письмо в формате HTML, используя уже созданное представление. Это означает, что вы хотите получить результат чего-то похожего на следующее:

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

и отправьте это как тело письма. Вы можете повторно использовать свои взгляды и все эти забавные вещи.

Вы можете воспользоваться преимуществами этой инфраструктуры, создав собственный 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);
        }
    }
}

Это переопределяет базовый метод ExecuteResult (это код из базового метода, который я переопределяю; возможно, изменился в RC1) для рендеринга в поток, которым я управляю, вместо потока вывода ответа. Таким образом, он извлекает текст именно так, как он будет представлен клиентскому компьютеру.

Далее, как бы вы использовали это в действии контроллера:

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;
}

Я представляю один и тот же вид дважды; в первый раз я рендерил его в поток, а во второй раз я рендерил его как обычно. Возможно, можно проникнуть в цепочку вызовов ViewResult где-нибудь еще и изменить работу Render, но беглый взгляд на код ничего не показывает. Несмотря на то, что фреймворк довольно хорош, стек вызовов для отдельных частей процесса просто недостаточно детализирован, чтобы можно было легко изменить один шаг процесса. Если бы они разбили ExecuteResult на несколько различных переопределяемых методов, мы могли бы изменить его с рендеринга на выходной поток на рендеринг в наш поток без переопределения всего метода ExecuteResult. Ну что ж....

Вот как получить представление в виде строки.

У меня недостаточно представителей, чтобы комментировать, но я решил сэкономить время, указав, что принятый ответ сработает, и было бы замечательно, если бы он сработал. Тем не менее, кажется, что WebForm View Engine просто ест параметр TextWriter. Больше информации здесь: http://ayende.com/Blog/archive/2008/11/11/another-asp.net-mvc-bug-rendering-views-to-different-output-source.aspx

http://www.brightmix.com/blog/renderpartial-to-string-in-asp-net-mvc/ предлагает хорошее решение для отображения представления в строке, чтобы вы могли отправить его по электронной почте. Он отмечает, что "рендеринг частичного представления в строку, к счастью, стал намного, намного проще".

/// 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();
}

MvcMailer получил именно то, что вы ищете. Смотрите пакет NuGet здесь и проектную документацию

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

Есть хорошая статья о том, как использовать RazorEngine для этих целей: Как создать локализуемый движок текстовых шаблонов с помощью RazorEngine

Эта статья дала лучший ответ для меня:

Отобразить любой ASP.NET MVC ActionResult в строку

Вы не можете видеть само представление внутри контроллера. Способ сделать то, что вы просите, - написать собственный подкласс ActionResult и собственный ViewEngine для его обработки. Переопределите ExecuteResult, чтобы фактически отправить электронное письмо. Посмотрите на Spark с открытым исходным кодом, NHAML и т. Д., Посмотрите движки для MVC для примеров.

Привет, Уилл, из того, что я читаю (и из моей собственной попытки реализовать ваше решение), метод View.Render полностью игнорирует параметр записи. Содержимое моего писателя всегда пусто, и вместо этого визуализированное представление выпадает в поток ответов. Таким образом, кажется невозможным (или, по крайней мере, запутанным), чтобы получить ваши взгляды, как это. Я думаю, что в вашем тестовом примере вы бы увидели визуализированный вид дважды, и ваш адрес электронной почты был бы пустым.

Я нашел кое-что по этому вопросу здесь: http://ayende.com/Blog/archive/2008/11/11/another-asp.net-mvc-bug-rendering-views-to-different-output-source.aspx

Другие вопросы по тегам