Thursday, 3 October 2013

Executing Razor Views outside of a web application with NonHttpRunTimeRazorSupport

NonHttpRunTimeRazorSupport (catchy) is a small library that allows you to use ASP.Net MVC Razor views to render content outside of the context of a running ASP.Net application  with full support for Layouts, _ViewStart inclusion, Partials, built-in HtmlHelpers etc.


Introduction

Razor views are a really nice mechanism for generating web page content within an ASP.Net MVC application. They're so great in fact, that it's a shame to use them just to render HTML to display in a browser. What if we could use them to generate other content within our application, like email messages?

Many applications need to send emails. For something simple, like a one-off message to a site administrator, you might be able to get away with using a StringBuilder to generate the content of the email. If you need to send a range of rich HTML emails and want developers to be able to modify them easily, a full-blown template system like Razor is a much more flexible and maintainable mechanism.

Another common requirement is to send emails in an "offline" scenario. By "offline", I mean outside of the context of an HTTP request in a running ASP.Net application. Maybe you want to send emails within a console app, Windows service or an NServiceBus / MassTransit / Rebus message handler.

NonHttpRunTimeRazorSupport lets you use all of Razor's features outside of a running web app.

There are loads of other things you could use this library for - but email is probably one of the most common requirements it supports.

How it Works

The library is on GitHub at https://github.com/danmalcolm/NonHttpRunTimeRazorSupport. If you know about git, go ahead and clone the repo on your development machine, otherwise you can download a zip file of the source or browse the code directly on GitHub.

This solution uses RazorGenerator, a great tool that allows you to pre-compile Razor views at design time. As you edit your Razor views in Visual Studio, a pre-compiled view (an accompanying C# class file a bit like a web forms Something.aspx.Designer.cs file). Pre-compiled views can be used instead of .cshtml files that are compiled on-the-fly by RazorViewEngine. One thing that the RazorGenerator project is missing is an example of how to render pre-compiled Razor views in the "offline" context we introduced above*.

Razor View templates, whether compiled at design-time by RazorGenerator or at runtime by RazorViewEngine, are instances of WebViewPage. Views of this type are designed to execute in the context of an HTTP request. The standard built-in RazorViewEngine assumes a web request and other supporting infrastructure offered by HttpRuntime to be present when locating and rendering Razor views. 

The main purpose of NonHttpRunTimeRazorSupport is to work around this limitation. A customised ViewEngine and fake implementations of HttpContext (and it's HttpRequest, HttpResponse members) are used to support the execution of Razor Views.

Needless to say, you have to write your templates with this "offline" context in mind. Putting something like @HttpContext.Current.Request.ServerVariables[...] in the middle of your template would result in an exception. Note that the library attempts to provide help here by throwing an exception with an informative message if  any non-supported HttpContext (and family) members are accessed.

Getting Started

See the README for details on how to get up and running.

The repository includes a simple EmailDemo console app, that demonstrates how you might handle sending emails in your application.

The EmailNotificationService class uses Razor templates to render email content, using a convention to locate views based on the name of the model type. Here's how the views are structured:


This foundation would allow you to support a range of emails without adding a great deal of code. For each message type, you would simply need to add a model and Razor templates to render the subject, text and html body content. Here's the code for EmailNotificationService in full:

Look at EmailNotificationService.cs on github if you can't see the code in-line above.

Alternatives

There are other libraries that allow you to use Razor templates to generate email content, such as MvcMailer and ActionMailer, but, they don't fully support sending Razor-templated emails in an "offline" scenario ("Email sending from a background process" is still listed as an upcoming feature on the MvcMailer Wiki page and the standalone version of ActionMailer doesn't appear to support layouts and other Razor features.

What Next?

I'll consider adding a NuGet package once I've got feedback from using this approach on some other projects. Any comments or feedback would be great.

I came up with this solution while working on a project that was already using RazorGenerator. I'm interested in exploring whether it would be possible to bypass RazorGenerator and compile the views on the fly. Compiling Razor views from templates stored in a data store could also be interesting....

Happy mailing!

* I should point out that views compiled with the RazorGenerator "Template" generator can run outside of the context of an ASP.Net application. They are not the same thing as standard MVC Razor views - the declarative Layout property, _ViewStart pages, partials, HtmlHelper / UrlHelper etc are not available.


27 comments:

  1. Email is one of those things that could easily be offloaded to a background service. Sadly, MvcMailer gives me access to the HttpContext which allows me to generate urls respective to my environment. Not a huge deal, but can be very helpful when you have a dev, staging, and production environment. I guess the easy solution to that is just creating app settings with the proper base url.

    ReplyDelete
    Replies
    1. This solution renders templates with a special implementation of HttpContext to support "offline" use, with the properties needed to support UrlHelper etc. It's pretty nice to be able to use the following in an email template rendered by a console app:

      <a href="@Url.Absolute("~/tnc")">terms and conditions</a>

      You need to supply the base URL when you render the template, e.g.:

      string content = renderer.RenderView(model, baseUri);

      I see what you're saying - rendering an email directly within a web app means that it automatically uses the right host name in URLs. Usually, a background service will have a separate deployment per environment, e.g. test and production, so the config file solution isn't too difficult.

      If you're queueing email from more than one site to be sent by a shared background service, you could include the base URL in the command / message ... whatever you're using.

      In one project scenario (multi-tenant e-commerce), a background service gets the URL for each storefront site from the database.

      Delete
  2. Interesting how does this compare with Matthew Abbott's RazorEngine that is already a Nuget package ? I've tried the RazorEngine, but I'm struggling a bit to do anything more than the basics due to the lack of documentation. I will try this tool as well and see how far I can get. Thanks for your efforts !

    ReplyDelete
  3. Có làn da trắng là mong ước của mọi cô gái , sản phẩm thuoc ivory caps giúp làm trắng da toàn thân ngoài ra bạn cũng có thể sử dụng các loại loai kem chong nang tot nhat. Ngoài ra nếu bạn muốn làn da luôn tươi trẻ thì nên dùng my pham sakura nhat ban như kem duong da chong lao hoa sakura giúp làn da luôn trẻ đẹp xóa các nếp nhăn. Cách thuoc herba vixmen an toàn và hiệu quả bằng herba vixmen , vậy thuoc herba vixmen mua o dau , có an toàn không và mua ở đâu sẽ được cho biết sau đây.

    ReplyDelete
  4. đồng tâm
    game mu
    cho thuê nhà trọ
    cho thuê phòng trọ
    nhac san cuc manh
    số điện thoại tư vấn pháp luật miễn phí
    văn phòng luật
    tổng đài tư vấn pháp luật
    dịch vụ thành lập công ty trọn gói
    64 nước cờ trên bàn thương lượng ebook
    mbp là gì
    thuyết erg
    các nghịch lý nổi tiếng
    chi square test là gì
    nghệ thuật nói chuyện trước công chúng dale carnegie
    định lý coase
    học thuyết kỳ vọng của victor vroom
    chiến thắng con quỷ trong bạn audio
    điểm cân bằng nash

    Mấy cô bé mới vào trường đại học, không hiểu mấy về mưa gió ngoài xã hội, rất nhiều lúc đều tự cho mình là đúng. Triệu Quốc Đống không khỏi thầm than mình tính ra mới ra ngoài xã hội vài năm nhưng đã không còn nhiệt huyết và hoài bão như xưa. Không biết do nghề cảnh sát hay giấc mơ kia khiến hắn thay đổi?

    - Kiều San, Quốc Đống ca của mình tốt nghiệp trường cảnh sát tỉnh, phá án là bản lĩnh của anh ấy.
    Cổ Tiểu Âu có chút không vui khi bạn học của mình coi thường Triệu Quốc Đống.

    - Là thần thám như Sê-Lốc Hôm không?
    Kiều San không vì Cổ Tiểu Âu nhấn giọng mà đổi cách nói chuyện.

    Triệu Quốc Đống có chút xấu hổ gãi đầu. Hắn phát hiện muốn đấu miệng lưỡi với các cô gái là sai lầm lớn nhất. Các cô vốn thích khiêu khích người khác, nhất là người có vẻ cao lớn hơn các cô. Mà hắn không may chính là nhân vật như vậy.

    - Được rồi, được rồi, anh chỉ là chân chạy kiếm cơm mà thôi, không cần phải tìm cách đả kích anh như vậy chứ?
    Triệu Quốc Đống giơ tay lên xin hàng:
    - Không dám ra vẻ trước mặt các em là được chứ gì?

    Mấy cô gái đều bị vẻ khôi hài của Triệu Quốc Đống làm cho buồn cười, ngay cả Lam Đại cũng nở nụ cười.

    - Quốc Đống ca, vậy tối anh về Giang Khẩu à?
    Cổ Tiểu Âu hỏi.
    - Anh không về, anh ở khách sạn An Đại, đợi lát nữa kết thúc mới có thể về.
    Triệu Quốc Đống lắc đầu nói:
    - Bây giờ khai mạc đã xong, mấy em có thể về, sao còn không đi?

    - Anh có ý gì, muốn đuổi bọn em đi ư? Sợ bọn em đòi anh mời ăn trưa sao?
    Cổ Tiểu Âu chu môi nói:
    - Nhiều người đẹp ở đây như vậy, người khác muốn mời còn xem bọn em có tâm trạng hay không, cho anh cơ hội mà anh không nắm bắt ư?

    ReplyDelete
  5. Thank you for taking the time to provide us with your valuable information. We strive to provide our candidates with excellent care.As always, we appreciate your confidence and trust in us.. Peridot Systems Complaints

    ReplyDelete
  6. I truly appreciate this post. I’ve been looking all over for this! Thank goodness I found it on Bing. You have made my day! Thanks again! Keep update more excellent posts..

    Digital marketing company in Chennai

    ReplyDelete
  7. It is different from traditional marketing in terms of the use of components and methods that support an organization to review marketing strategies and understand what is gaining results and what is not in actual. Social Media Marketing

    ReplyDelete
  8. As more than 90% consumers find on internet and they are looking for the search engine marketing experts on internet.M3 places your business offers in front of those consumers who are looking for you. We place your site ratings in top of the links. best SEO near me

    ReplyDelete
  9. I Will Provide SEO Blog Comment Service. & niche relevant blog comment service we provide a quality service with 100% Buyer satisfaction and My team Believed in Quality work not Quantity Contact me Now 24/7.check out this Blog for your business . your business will be gain 200% more profit I can not recommend you guys enough. SEO

    ReplyDelete
  10. I go into how you should build links and where those links should be pointing, I want to make myself clear about what an effective link is. accounting firm seo

    ReplyDelete
  11. There are few things that must be taken care of while taking web designing training. The overall forms and shapes, font and color selection should be done cautiously. The font and the color of the website must be appealing as they are the factors which will attract visitors to the website. web design inspiration

    ReplyDelete
  12. I recently came across your blog and have been reading along. I thought I would leave my first comment.
    web agency ideas

    ReplyDelete
  13. What if we could use them to generate other content within our application, like email messages?Web design

    ReplyDelete
  14. The Wolf Of Online Marketing is your one stop source for honest Internet Marketing products reviews and Online Marketing news with exclusive bonuses for our readers.
    CPA Product Reviews

    ReplyDelete
  15. There are actually quite a few companies that offer Craigslist posting services so as to take the burden of posting off your shoulders. The many choices of services can make the process of choosing one difficult, but one of the important things to remember is that quality over quantity tends to be more effective. CRAIGSLIST POSTING SERVICE

    ReplyDelete
  16. Consider a domain name that represents your business name, product name, or indicates your type of business. Namecheap Hosting coupon

    ReplyDelete
  17. If you’re looking for excellent Workers.We are here to provide Internet Marketing services and help people. We offer NICHE Relevant Manual Blog Comment Service , We can rank you for any keyword on Google I will be very happy to offer my service to you. Please feel free to message me and talk about any queries

    ReplyDelete
  18. If you’re looking for excellent Workers.We are here to provide Internet Marketing services and help people. We offer NICHE Relevant Manual Blog Comment Service , We can rank you for any keyword on Google I will be very happy to offer my service to you. Please feel free to message me and talk about any queries

    ReplyDelete
  19. Shrewdly worked by the creator and Stunningly delightful usage of words.Web design in Kearney NE

    ReplyDelete
  20. If you like the company's website and feel that it has the desired feature that you want in your corporate web design, you should go for it. our website

    ReplyDelete
  21. Simply put, the search engines do not follow these links away from your site. Unfortunately, this also has a negative impact upon legitimate comments left by other internet users. Dofollow Backlink

    ReplyDelete
  22. Hello, I will Provied SEO Niche Blog Comment Service . All comment relevant with your blog. I know every tips of niche blog comment . This service bring you lots of traffic . We Just say the post be real. That showing your personality is much more important than showing off your knowledge in the niche.

    ReplyDelete
  23. hi was just seeing if you minded a comment. i like your website and the thme you picked is super. I will be back. seo expert

    ReplyDelete
  24. If I had to use one word to describe this blog it would be GRANDILOQUENT.
    responsive wordpress website

    ReplyDelete