2009-02-06 4 views
22

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

Псевдо-код:

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

    return new EmptyResult(); 
} 
+0

Можете ли вы уточнить, что вы хотите сделать? –

+0

С псевдо? Яснее? –

+0

Запросы веб-серверу необходимо вернуть * что-то. * Что вы ожидаете от него? HTML? JSON? Что-то другое? Или вы спрашиваете, как отправлять электронную почту? Нет, пока не ясно. –

ответ

1

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

14

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

+0

Somewhy не работает для меня. Html пуст в конце. :/ –

+0

Обычно имеет отношение к потоку. Вы пишете html в потоке, затем пытаетесь передать этот поток кому-то другому, они, вероятно, не захотят вернуться к началу. Ищите 0, и вы найдете свой HTML. – Will

+2

Святое дерьмо .... MVC 1 полностью игнорирует поток и просто пишет ответ. http://ayende.com/Blog/archive/2008/11/11/another-asp.net-mvc-bug-rendering-views-to-different-output-source.aspx Интересно, исправили ли они это в 2 ? – Will

6

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

+0

Это действительно запутанный вопрос! Я думаю, что для большинства людей, заканчивающихся здесь, это то, что они просто хотят! этот вопрос на самом деле даже конкретный вопрос о получении вида для электронной почты внутри другого контроллера –

6

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

0

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

Я нашел обсуждение на этом здесь: 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/ имеет хорошее решение для рендеринга 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(); 
} 
1

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

Render any ASP.NET MVC ActionResult to a string

+0

Как этот ответ не поддерживается больше? Это, безусловно, самый быстрый, самый простой и охватывает вопрос ОП наиболее полно по сравнению со многими другими, более верными ответами. –

Смежные вопросы