Отправить asp.net результат действия MVC внутри электронной почты - PullRequest
22 голосов
/ 06 февраля 2009

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

Псевдо-код:

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

    return new EmptyResult();
}

Ответы [ 9 ]

13 голосов
/ 06 февраля 2009

Во-первых, вы все равно, вероятно, захотите вернуть представление из вашего действия, поэтому возвращение 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. Ну да ладно ....

6 голосов
/ 08 февраля 2009

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

6 голосов
/ 06 февраля 2009

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

5 голосов
/ 04 марта 2010

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();
}
2 голосов
/ 09 марта 2011

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

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

1 голос
/ 19 апреля 2012

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

1 голос
/ 01 декабря 2011

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

Отображение любого ASP.NET MVC ActionResult в строку

1 голос
/ 06 февраля 2009

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

0 голосов
/ 24 марта 2009

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

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

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