Ответ 1
Сначала вы, вероятно, захотите вернуть представление из своего действия, поэтому возврат EmptyResult не самый лучший; но вы поймете это, когда будете иметь дело с потоком страницы в процессе регистрации.
Я предполагаю, что вы хотите создать HTML-адрес электронной почты, используя View, который вы уже создали. Это означает, что вы хотите взять результат чего-то, что выглядит следующим образом:
public ActionResult CreateEmailView(RegistrationInformation info)
{
var userInformation = Membership.CreateNewUserLol(info);
return View(userInformation)
}
и отправьте это как тело письма. Вы можете повторно использовать свои взгляды и все эти забавные вещи.
Вы можете воспользоваться каркасом, создав пользовательский ActionResult и используя его для генерации вашего текста.
Вот некоторый псевдокод С#, который может действительно скомпилироваться и работать. Во-первых, пользовательский 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), чтобы рендерить в поток, который я управляю вместо выходного потока 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;
}
Я делаю одно и то же представление дважды; в первый раз я передаю его потоку, а во второй раз я его делаю нормально. Возможно, можно прокрасться в цепочку вызовов ViewResult где-то еще и изменить, как работает Render, но беглый взгляд на код ничего не обнаруживает. Несмотря на то, что структура довольно хороша, стек вызовов для частей процесса просто недостаточно хорош, чтобы упростить изменение одного шага в этом процессе. Если они нарушили ExecuteResult в несколько различных переопределяемых методов, мы могли бы изменить его от рендеринга к выходному потоку до рендеринга в наш поток без переопределения всего метода ExecuteResult. О, хорошо...