I have an ASP.NET MVC solution, and I have a large number of HtmlHelper classes inside the ASP.NET MVC project that take data and generate various snippets of html to display on various pages.
我有一个ASP。NET MVC解决方案,我在ASP中有大量的HtmlHelper类。NET MVC项目,它接收数据并生成各种html片段以显示在不同的页面上。
I now have to run a bunch of scheduled jobs and many of those jobs generate emails. I moved all of these jobs into a separate project in the solution (called AdminJob.csproj), but I now find that I have to generate a number of email with very similar HTML as I have in my view pages. I am trying to keep the admin jobs from having a dependency on the ASP.NET MVC project (as I would like to run the adminjob project as a command line if required), and I also want to avoid having my ASP.NET MVC project having a dependency on the AdminJob project (as that just seems odd).
我现在必须运行一堆预定的工作,其中许多工作产生电子邮件。我将所有这些工作迁移到解决方案中的一个单独的项目中(称为AdminJob.csproj),但是现在我发现我必须生成大量具有与视图页面非常相似的HTML的电子邮件。我试图让管理工作不依赖于ASP。NET MVC项目(如果需要的话,我希望将adminjob项目作为命令行来运行),我还希望避免使用我的ASP。NET MVC项目依赖于AdminJob项目(这看起来很奇怪)。
Any suggestions on how I can avoid duplicating the same HTML rendering code in both my ASP.NET MVC project and my AdminJob project?
关于如何避免在我的ASP中重复相同的HTML呈现代码的任何建议。NET MVC项目和我的AdminJob项目?
The only thing I can think about is creating another project in the solution called "ViewHelpers" or something like that and move all of my HTMLHelpers into that project so it can be referenced by both my MVC project and the AdminJob project. It seems a bit overkill to have a separate project just for this code, but I can't think of another solution that doesn't create duplication.
我能想到的唯一一件事就是在名为“ViewHelpers”的解决方案中创建另一个项目,并将我的htmlhelper全部移到这个项目中,这样它就可以被我的MVC项目和AdminJob项目引用。对于这个代码来说,有一个单独的项目似乎有点过分了,但是我想不出另一个不产生重复的解决方案。
Any other suggestions for a better way to do this and avoid any duplication?
还有什么更好的方法来避免重复吗?
3 个解决方案
#1
6
The way I look at this is that the email is a view type.There are several view types in my web apps (html, email, pdf, rss etc). There are several implementations of this pattern: ActionMailer in ruby on rails or its port to asp.net: MvcMailer.
我的看法是,电子邮件是视图类型。我的web应用程序中有几种视图类型(html、电子邮件、pdf、rss等)。该模式有几个实现:ruby on rails中的ActionMailer或其到asp.net: MvcMailer的端口。
This way you can take full advantage of the Razor engine in both your web application and your emails in order to reduce duplication.
这样,您可以充分利用您的web应用程序和电子邮件中的Razor引擎,以减少重复。
You can host your views in another project and inform your ViewEngine about where to look for the views (see Views in separate assemblies in ASP.NET MVC). I find this to be overkill.
您可以在另一个项目中托管您的视图,并通知您的ViewEngine在哪里查找视图(请参阅ASP中不同程序集中的视图)。净MVC)。我觉得这太过分了。
Another way - the one I use - is to have the email templates in the same project with other views.
我使用的另一种方法是将电子邮件模板与其他视图放在同一个项目中。
If you want to render the views outside of a web application you can compile the razor templates in a console app using one of these:
如果您想在web应用程序之外呈现视图,您可以使用以下其中之一在控制台应用程序中编译razor模板:
- RazorTemplates: https://github.com/volkovku/RazorTemplates
- RazorTemplates:https://github.com/volkovku/RazorTemplates
- RazorEngine: https://github.com/Antaris/RazorEngine
- RazorEngine:https://github.com/Antaris/RazorEngine
- with something like MvcMailer you can just make curl requests in your scheduled tasks. MvcMailer needs an HttpContext to run so you wouldn't be able to run it from a console app. curl the mvc actions would work.
- 使用MvcMailer之类的东西,您可以在计划的任务中发出curl请求。MvcMailer需要一个HttpContext来运行,这样您就不能从控制台应用程序运行它。
#2
1
Don't completely rule out the idea of having the AdminJob depend on the website. This might work for you: How to use Razor View Engine in a console application?.
不要完全排除让AdminJob依赖于网站的想法。这可能对您有用:如何在控制台应用程序中使用Razor视图引擎?
Note that the AdminJob having a compile-time dependency on the MVC project does not prevent the AdminJob running as a console app. That can work fine.
注意,在MVC项目上具有编译时依赖项的AdminJob不会阻止AdminJob作为控制台应用程序运行。
The problem I would expect — even if you move View-related stuff out into a shared project— is that you may find that it all breaks at runtime when running outside of the website. Under the hood, there are dependencies on System.Web
stuff, e.g. HttpContext
, which will be null at runtime. Some dependencies can be stubbed, some can't.
我所期望的问题是——即使您将与视图相关的内容移到共享项目中——您可能会发现,在运行于网站之外时,这些内容在运行时都会中断。在引擎盖之下,存在着对系统的依赖。Web内容,例如HttpContext,在运行时将为空。有些依赖项可以被存根化,有些则不能。
Being in a separate shared project won't fix this problem at all, so I don't think moving code about gains anything.
在一个单独的共享项目中根本解决不了这个问题,所以我不认为移动代码可以获得任何东西。
But the typical approach (i.e. 5 out of last 6 companies I've worked for) here is:
但是典型的方法(也就是我工作过的6家公司中有5家)是:
Forget the command line idea. Make the Admin tool part of the website. Whatever you think you wanted to run from the command line, run it from a push button on the admin tool instead.
忘记命令行思想。让管理工具成为网站的一部分。无论您想从命令行运行什么,都可以从管理工具上的按钮运行它。
PS
PS
“Email with very similar HTML as in my view pages” is a knot you should cut.
“电子邮件与我的视图页面非常相似”是一个你应该削减的结。
Either it is, or can be, identical to the view pages, in which case you want the AdminJob to reuse the view pages; or it isn't. In which case the AdminJob should have its own HTML. In this second case, take the line that there is no such thing as 'similar' HTML; if it's not the same, it's different.
它要么是,要么可以是,与视图页面相同,在这种情况下,您希望AdminJob重用视图页面;或不是。在这种情况下,AdminJob应该有自己的HTML。在第二种情况下,假设没有类似的HTML;如果不一样,那就不一样了。
#3
0
I understand the temptation to reuse the html from regular website pages into your email engine. However, I think that's a good example of over-engineering. That will create much more limitations long-run than the benefits you have short-run.
我理解将html从常规网站页面重用到电子邮件引擎的诱惑。然而,我认为这是过度设计的一个很好的例子。这将产生比短期利益更多的长期限制。
Think about couple of things:
想想以下几点:
HTML for emails is by design different from HTML for pages. Even though today they look similar, tomorrow they will look different. You just said it - 'email with very similar HTML as i have in my view pages', you didn't say 'with exact same HTML'.
电子邮件的HTML设计不同于网页的HTML。即使今天他们看起来很相似,明天他们就会不一样。你刚刚说过——“用和我的视图页面非常相似的HTML发邮件”,你没有说“用完全相同的HTML”。
HTML for email should not have any advanced HTML or any JavaScript in it. It should ideally have inline CSS and no JavaScript. The CSS compatible with email clients is very limited. Markup rules differ from the natural and modern way of writing it for regular browsers. Good example is email clients being friendly with tables, while in modern web you rarely use tables nowadays, especially if you want to stay responsive (cross-screen-platform-browser). Read about all limitations here: email-standards.org
电子邮件的HTML不应该包含任何高级的HTML或JavaScript。理想情况下,它应该具有内联CSS和JavaScript。与电子邮件客户端兼容的CSS非常有限。标记规则不同于为常规浏览器编写标记的自然和现代方式。一个很好的例子是,电子邮件客户端对表很友好,而在现代web中,你现在很少使用表,尤其是如果你想保持响应性(跨屏-平台-浏览器)。在这里阅读所有的限制:电子邮件-标准。org
HTML for modern web does not have to be so static as email message has to be.
现代web的HTML不需要像电子邮件那样静态。
These all reasons are the idea behind popular commercial email senders online. They help you create an email distribution list and they take the headache to generate the proper limited HTML on their shoulders. Otherwise, would would they exist? anybody could send group emails if not the markup differences.
这些原因都是网络上流行的商业电子邮件发送者的想法。它们可以帮助您创建一个电子邮件分发列表,并且它们可以在肩上生成适当的有限的HTML。否则,它们会存在吗?如果没有标记差异,任何人都可以发送组电子邮件。
My conclusion from all this: if you decide to use your web page markup for the emails, you are limiting both. You are over-engineering. It will be much simpler if you don't reuse the regular page markup into your email messages. I understand they are similar today, but they may not be tomorrow.
我的结论是:如果您决定在电子邮件中使用web页面标记,那么您就限制了这两种标记。你是系统的过度设计。如果不将常规页面标记重用到电子邮件消息中,就会简单得多。我知道他们今天很相似,但明天可能不会。
Obviously, it's a good idea to have templating capabilities for your email engine (has nothing to do with reusing web pages markup). For that you could use any of the existing templating engines, or you could quickly write yours (after all, dirty string.Replace() will replace placeholder with the value if you have HTML message template as string, loaded from file or database).
显然,为您的电子邮件引擎提供模板功能是一个好主意(与重用web页面标记无关)。为此,您可以使用任何现有的模板引擎,或者您可以快速地编写您的模板引擎(毕竟,dirty string. replace()将替换占位符,如果您将HTML消息模板作为字符串,从文件或数据库加载)。
In other words, to directly answer your question: don't hesitate to diverge the two paths of web pages and emails. Avoid sharing capabilities, as they mostly differ. Consider the two in isolation from each-other.
换句话说,直接回答你的问题:不要犹豫,把网页和电子邮件这两条路分开。避免共享功能,因为它们大多是不同的。想想这两个彼此孤立的个体。
#1
6
The way I look at this is that the email is a view type.There are several view types in my web apps (html, email, pdf, rss etc). There are several implementations of this pattern: ActionMailer in ruby on rails or its port to asp.net: MvcMailer.
我的看法是,电子邮件是视图类型。我的web应用程序中有几种视图类型(html、电子邮件、pdf、rss等)。该模式有几个实现:ruby on rails中的ActionMailer或其到asp.net: MvcMailer的端口。
This way you can take full advantage of the Razor engine in both your web application and your emails in order to reduce duplication.
这样,您可以充分利用您的web应用程序和电子邮件中的Razor引擎,以减少重复。
You can host your views in another project and inform your ViewEngine about where to look for the views (see Views in separate assemblies in ASP.NET MVC). I find this to be overkill.
您可以在另一个项目中托管您的视图,并通知您的ViewEngine在哪里查找视图(请参阅ASP中不同程序集中的视图)。净MVC)。我觉得这太过分了。
Another way - the one I use - is to have the email templates in the same project with other views.
我使用的另一种方法是将电子邮件模板与其他视图放在同一个项目中。
If you want to render the views outside of a web application you can compile the razor templates in a console app using one of these:
如果您想在web应用程序之外呈现视图,您可以使用以下其中之一在控制台应用程序中编译razor模板:
- RazorTemplates: https://github.com/volkovku/RazorTemplates
- RazorTemplates:https://github.com/volkovku/RazorTemplates
- RazorEngine: https://github.com/Antaris/RazorEngine
- RazorEngine:https://github.com/Antaris/RazorEngine
- with something like MvcMailer you can just make curl requests in your scheduled tasks. MvcMailer needs an HttpContext to run so you wouldn't be able to run it from a console app. curl the mvc actions would work.
- 使用MvcMailer之类的东西,您可以在计划的任务中发出curl请求。MvcMailer需要一个HttpContext来运行,这样您就不能从控制台应用程序运行它。
#2
1
Don't completely rule out the idea of having the AdminJob depend on the website. This might work for you: How to use Razor View Engine in a console application?.
不要完全排除让AdminJob依赖于网站的想法。这可能对您有用:如何在控制台应用程序中使用Razor视图引擎?
Note that the AdminJob having a compile-time dependency on the MVC project does not prevent the AdminJob running as a console app. That can work fine.
注意,在MVC项目上具有编译时依赖项的AdminJob不会阻止AdminJob作为控制台应用程序运行。
The problem I would expect — even if you move View-related stuff out into a shared project— is that you may find that it all breaks at runtime when running outside of the website. Under the hood, there are dependencies on System.Web
stuff, e.g. HttpContext
, which will be null at runtime. Some dependencies can be stubbed, some can't.
我所期望的问题是——即使您将与视图相关的内容移到共享项目中——您可能会发现,在运行于网站之外时,这些内容在运行时都会中断。在引擎盖之下,存在着对系统的依赖。Web内容,例如HttpContext,在运行时将为空。有些依赖项可以被存根化,有些则不能。
Being in a separate shared project won't fix this problem at all, so I don't think moving code about gains anything.
在一个单独的共享项目中根本解决不了这个问题,所以我不认为移动代码可以获得任何东西。
But the typical approach (i.e. 5 out of last 6 companies I've worked for) here is:
但是典型的方法(也就是我工作过的6家公司中有5家)是:
Forget the command line idea. Make the Admin tool part of the website. Whatever you think you wanted to run from the command line, run it from a push button on the admin tool instead.
忘记命令行思想。让管理工具成为网站的一部分。无论您想从命令行运行什么,都可以从管理工具上的按钮运行它。
PS
PS
“Email with very similar HTML as in my view pages” is a knot you should cut.
“电子邮件与我的视图页面非常相似”是一个你应该削减的结。
Either it is, or can be, identical to the view pages, in which case you want the AdminJob to reuse the view pages; or it isn't. In which case the AdminJob should have its own HTML. In this second case, take the line that there is no such thing as 'similar' HTML; if it's not the same, it's different.
它要么是,要么可以是,与视图页面相同,在这种情况下,您希望AdminJob重用视图页面;或不是。在这种情况下,AdminJob应该有自己的HTML。在第二种情况下,假设没有类似的HTML;如果不一样,那就不一样了。
#3
0
I understand the temptation to reuse the html from regular website pages into your email engine. However, I think that's a good example of over-engineering. That will create much more limitations long-run than the benefits you have short-run.
我理解将html从常规网站页面重用到电子邮件引擎的诱惑。然而,我认为这是过度设计的一个很好的例子。这将产生比短期利益更多的长期限制。
Think about couple of things:
想想以下几点:
HTML for emails is by design different from HTML for pages. Even though today they look similar, tomorrow they will look different. You just said it - 'email with very similar HTML as i have in my view pages', you didn't say 'with exact same HTML'.
电子邮件的HTML设计不同于网页的HTML。即使今天他们看起来很相似,明天他们就会不一样。你刚刚说过——“用和我的视图页面非常相似的HTML发邮件”,你没有说“用完全相同的HTML”。
HTML for email should not have any advanced HTML or any JavaScript in it. It should ideally have inline CSS and no JavaScript. The CSS compatible with email clients is very limited. Markup rules differ from the natural and modern way of writing it for regular browsers. Good example is email clients being friendly with tables, while in modern web you rarely use tables nowadays, especially if you want to stay responsive (cross-screen-platform-browser). Read about all limitations here: email-standards.org
电子邮件的HTML不应该包含任何高级的HTML或JavaScript。理想情况下,它应该具有内联CSS和JavaScript。与电子邮件客户端兼容的CSS非常有限。标记规则不同于为常规浏览器编写标记的自然和现代方式。一个很好的例子是,电子邮件客户端对表很友好,而在现代web中,你现在很少使用表,尤其是如果你想保持响应性(跨屏-平台-浏览器)。在这里阅读所有的限制:电子邮件-标准。org
HTML for modern web does not have to be so static as email message has to be.
现代web的HTML不需要像电子邮件那样静态。
These all reasons are the idea behind popular commercial email senders online. They help you create an email distribution list and they take the headache to generate the proper limited HTML on their shoulders. Otherwise, would would they exist? anybody could send group emails if not the markup differences.
这些原因都是网络上流行的商业电子邮件发送者的想法。它们可以帮助您创建一个电子邮件分发列表,并且它们可以在肩上生成适当的有限的HTML。否则,它们会存在吗?如果没有标记差异,任何人都可以发送组电子邮件。
My conclusion from all this: if you decide to use your web page markup for the emails, you are limiting both. You are over-engineering. It will be much simpler if you don't reuse the regular page markup into your email messages. I understand they are similar today, but they may not be tomorrow.
我的结论是:如果您决定在电子邮件中使用web页面标记,那么您就限制了这两种标记。你是系统的过度设计。如果不将常规页面标记重用到电子邮件消息中,就会简单得多。我知道他们今天很相似,但明天可能不会。
Obviously, it's a good idea to have templating capabilities for your email engine (has nothing to do with reusing web pages markup). For that you could use any of the existing templating engines, or you could quickly write yours (after all, dirty string.Replace() will replace placeholder with the value if you have HTML message template as string, loaded from file or database).
显然,为您的电子邮件引擎提供模板功能是一个好主意(与重用web页面标记无关)。为此,您可以使用任何现有的模板引擎,或者您可以快速地编写您的模板引擎(毕竟,dirty string. replace()将替换占位符,如果您将HTML消息模板作为字符串,从文件或数据库加载)。
In other words, to directly answer your question: don't hesitate to diverge the two paths of web pages and emails. Avoid sharing capabilities, as they mostly differ. Consider the two in isolation from each-other.
换句话说,直接回答你的问题:不要犹豫,把网页和电子邮件这两条路分开。避免共享功能,因为它们大多是不同的。想想这两个彼此孤立的个体。