views:

226

answers:

3

I have an .aspx page that I am using to handle the layout of an order receipt. I don't ever want the user to actually go to the page, I just want to populate the fields on the page and then render the HTML into a MailMessage that gets sent of to a customer. Currently I have been able to accomplish this by using Server.Execute("~/myreceipt.aspx?orderId=12345", writer) to render the HTML to a writer which I then place into the message body.

The problem with this is approach is that it limits me to either passing in the orderId to the receipt page and making a database call to pull the order info and populate the fields, or to passing each individual field via the query string and the populating the data that way (e.g ~/myreceipt.aspx?orderId=12345&customerName=John%20Smith", etc) which is rather cumbersome. What I'd LIKE to do is to pass an entire object to the aspx page in my code-behind via some property I create and then populate it that way. This way I can easily reuse the same information to pass along to multiple views, such as an order notificiation for the sales team. Since I know that ASP.NET treats all its pages as a class, I was thinking I might be able to accomplish something like:

Dim receipt As New ReceiptPage
receipt.OrderInfo = myOrderInfo

msg.Body = receipt.Render()

Does anyone know if this or a similar approach is possible?

Any help is greatly appreciated,

Mike

+2  A: 

ASP.Net pages are just plain old .Net classes that inherit a certain base type, and you can create instances just like any other class. But the process to correctly render the html for that page is... complicated. I wouldn't recommend doing it that way.

I originally thought you might just use a custom control instead, but re-reading your question I see this is for sending via e-mail, and so a custom control is not as good a fit.

But I still say that an asp.net page is overkill, because you won't have to worry about things like postbacks, query strings, session, etc. You are essentially just plugging template values in a string variable, even if one of those template positions (a receipt grid) is a little more complicated or could itself be a template string.

This may be a rare case where something like my CompiledFormat implementation is a better fit.

Joel Coehoorn
By custom control do you mean UserControl or the more advanced Custom Server Control? I know that a UserControl does have a RenderControl() method, would using that method require the same complicated process used on .aspx pages?
Mike C
Sorry, I re-read your question and a custom control may not be a good fit. I removed that part, will have something better in a few minutes.
Joel Coehoorn
Thanks for your response,The problem is that the e-mail I want to send is in HTML, not plain text. In my .aspx I utilize controls such as labels and most importantly a DataGrid to help layout the information. While it may be a bit of overkill to use an actual .aspx page, my gut says that it would be less involved than trying to accomplish a similar layout via text (although I do believe that text emails have a much higher delivery rate). I'm going to give using a UserControl a shot first before completely giving up on my approach.
Mike C
umm... html is plain text as far as your code is concerned. A label control is essentially just a span tag with a placeholder.
Joel Coehoorn
Fair enough, but what do you suggest as the best method for encapsulating the layout? Should I just write a simple HTML page and then substitute {0}'s and {1}'s where I have labels now? Then open the filestream, read it as a string and then perform the formatting to substitute the actual field values?
Mike C
I actually like the xsl transform idea, but reading your string from a file should do fine. The only trick is the grid, and I gave you hint about how to do that already (read carefully ;)
Joel Coehoorn
+2  A: 

I understand that this doesn't directly answer your question, but if you're trying to take some data and format an HTML message, an XSL Transform might be a cleaner approach. This worked very well for me a few years ago on the same kind of project. It's much lighter-weight than an entire aspx page (especially with a DataGrid), and it's easy to load and manipulate in .NET.

There is a bit of a learning curve, but I didn't think it was too bad. I picked up most of what I needed to know from the tutorials here: http://www.w3schools.com/xsl/default.asp

If you like Visual Studio's designer and don't want to write the whole thing by hand, you can start with an ASPX page that has the layout you want, view in a browser, and save off the source as a starting point. For laying out your repeated data, I'd use a Repeater instead of a DataGrid - a DataGrid carries along a huge amount of information you won't need if you're not doing postbacks, and once you've got the layout you want, you can just replace the repeater tag with an XSL for-each. .NET's built-in XML serialization should allow you to get your underlying data into XML in only a couple of lines of code.

For my project, Altova's XMLSpy helped a lot - I saved some sample XML into one pane and used a second pane to tweak my XSLT until the results were what I wanted. This was a few years ago; there may be other good tools available now.

In my experience, controls like DataGrids are great when you're using them for exactly their intended purpose, but once you move outside that - like this project - you'll spend just as much time fighting with them as you would creating something like an XSLT by hand, and have far less control over the results.

Lastly: You're right about HTML email. They're to be avoided, but when they can't be, you want to make sure the HTML you're sending is as clean and simple as possible. You're much more likely to get that result if you create a clean template than if you rely on .NET's rendering. Your recipients will likely be using all different email clients, and Outlook and Lotus (for example) behave very differently when displaying an HTML message. Creating messages that looked decent in both of those was the largest hurdle on my project, not generating the HTML in the first place.

I hope that's helpful, and not too far off-topic.

Jeremy Gruenwald
Jeremy, Thanks for the response. I'll certainly look into learning about XSLTs as a possibility. If what little I know about them is true, they could come in quite handy for systems integration scenarios.
Mike C
A: 

Won't it be possible for you store the object that needs to pass along in a Session variable and read the same in the Code behind of ReceiptPage before processing the ReceiptPage's information... In that case you can use the methodology you suggested in the question itself. (Server.Execute())

Just a thought.

The King