可重复使用的地方放置电子邮件视图渲染逻辑?
我有一个名为 EmailController 的控制器,它(你猜对了)负责发送电子邮件。
一个例子是,我网站的用户可以“收藏”事物,如果其他用户对其中一个“事物”执行某些操作,那么我需要向所有“收藏”它的用户发送一封电子邮件。有点像电子邮件警报。
问题是,我不确定如何从其他操作方法(即用户执行某些操作时的 HTTP POST)调用我的 EmailController 的操作方法。
通常我会将这种操作(电子邮件)放入服务中,实际的电子邮件逻辑(SMTP)位于服务中,但EmailController负责设置电子邮件的内容(例如 HTML),需要将视图呈现为字符串(因此,它需要控制器上下文并且无法进入服务)。
我怎样才能做到这一点?
我不能只使用静态辅助方法,因为我如何渲染视图?我需要将控制器上下文传递给方法或其他东西。
示例流程:
- 用户 A 转到页面并提交表单。
- HTTP POST ControllerAActionMethodA 被调用,数据提交到DB。
- 卡住。
因此,在第 3 步,我需要: 从
- 刚刚发布的数据中提取一些信息
- 创建一个视图模型
- 将强类型视图渲染为字符串
- 调用我创建的服务方法来发送 SMTP 电子邮件
目前,我有 2 /3/4 位于 EmailController 上方,所以我希望使用它。
作为旁注,我希望使电子邮件发送异步(因为刚刚创建一些数据的用户不关心其他用户需要收到电子邮件)。
任何人都可以给我一些关于如何组织这些单独的问题的建议(提交数据、将 HTML 视图创建为字符串、发送电子邮件)。
也许基本控制器中的 HTML 帮助器或受保护方法是比控制器更好的选择?
仅供参考,这是我的“查看字符串”方法(我从另一个堆栈问题中提取,并且效果很好):
protected string RenderViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.RouteData.GetRequiredString("action");
ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindView(ControllerContext, viewName, null);
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
I have a controller called EmailController, which is (you guessed it) responsible for sending emails.
An example of this is that users of my site can "favorite" things, and if some other user does something on one of those "things", then i need to send an email out to all users who "favourited" it. Kind of like an email alert.
The problem is, im not sure how to call my EmailController's action method, from the other action method (which is the HTTP POST for when a user does something).
Normally i would put this kind of operation (emailing) into a service, and the actual emailing logic (SMTP) is in a service, but the EmailController is responsible for setting up the content of the email (e.g the HTML), for which is needs to render a View to a string (hence, it needs a controller context and cannot go into a service).
How can i achieve this?
I can't just use a static helper method, because how can i render the view? I would need to pass the controller context to the method or something.
Example flow:
- User A goes to a page and submits a form.
- HTTP POST ControllerAActionMethodA called, data submitted to DB.
- Stuck.
So at step 3, i need to:
- Pull some info out of the data just POST'ed
- Create a viewmodel
- Render a strongly-typed View to a string
- Call a service method i've created to send a SMTP email
Currently, i have 2/3/4 above in EmailController, so i was hoping to use that.
As a side note, i was hoping to make the emailing asynchronous (since the user who just created some data doesnt care that another user needs to get emailed).
Can anyone give me some advice on how to organize these seperate concerns (submitting data, creating HTML view into string, sending email).
Perhaps a HTML helper or a protected method in a base controller is a better option than a controller?
FYI, here's my "View to string" method (i pulled from another Stack question, and works great):
protected string RenderViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.RouteData.GetRequiredString("action");
ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindView(ControllerContext, viewName, null);
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以查看 nuGet 中的 ActionMailer 包。那么您就不需要单独的控制器。
You could take a look at the ActionMailer package from nuGet. Then you don't need a seperate controller.