Geeks With Blogs
Adrian Hara Working through the .NET maze

In the current project I'm working on, we have to have an “export to pdf” functionality for each page. So we've been using webSupergoo's ABCPDF successfully until yesterday, when I found that we could change the way we're inserting the css stylesheet into the pages for the better. We used to do this:

<link rel="stylesheet" href="<%= ResolveUrl(AppConfigurator.CssFile) %> <%= ResolveUrl(AppConfigurator.CssFile) %>" type="text/css">

...where AppConfigurator is a static class holding a reference to a static NameValueCollection, wrapping web.config's <appSettings> element. This way changing the stylesheet is a matter of changing a value in the web.config file. Still, I thought this solution is a bit cumbersome and when I learned that we could leverage 2.0's Themes feature, I jumped for it. The idea is that, using Themes, inserting a <link> on each page is no longer necessary. Just add an App_Themes folder to the web site, add a new subfolder for each theme (say App_Themes\Default) and add your stylesheet files to that folder (like App_Themes\Default\Default.css). Then, when defining a theme for a page, will automatically insert a link to any stylesheets found in the selected theme's folder (the only condition being that you must have head runat=”server”). What's really cool is that you don't have to declare the theme to use for each page individually, but have a <pages theme=“Foo“>  in your web.config file and that theme gets applied to all pages. So this is exactly what I did, and it worked beautifully.

But, when doing an export to pdf of a page, bam! The exported page looked like a newborn, with no css on :), although the page itself was rendered fine in the browser. So what's going on? Maybe I should have said earlier, but the mechanism for export is this: we have a “export” page, which is kind of a container for the actual page to export. This page includes a div, into which the page to export is rendered. Then the whole page is sent to ABCPDF. Because ABCPDF is oblivious to what it's actually exporting, we have to include a <base> tag in the header of the “export” page, so images and other stuff get rendered correctly. The problem is that renders the href of the css it inserts relative to the current page's folder. Combine that with a <base> tag that says “http://myserver” and instead of getting “http://myserver/myApp/App_Themes/Default/Default.css” you get “http://myserver/../../../../App_Themes/Default/Default.css” for example.

The solution, in our case, is simple, because we do not need to export the whole requested page, but only part of it, so, as mentioned above, we render the part we need into another “wrapper” page, and that page gets sent to ABCPDF. So, before sending it we can do something like:

HtmlLink cssLink;
foreach (Control ctrl in this.Header.Controls)
    cssLink = ctrl
as HtmlLink;
    if (cssLink != null)
      cssLink.Href = ResolveUrl(cssLink.Href);

Still, I wonder what could be done if we needed to export the whole original page as is, because that would mean either resolving the url on each page before sending it to ABCPDF (maybe by deriving all pages from a common base page) or finding a way to make resolve the url to the css files itself, before inserting it into the <link>'s href. Or is there another way? And any idea why uses relative paths when inserting the href?

ps: the original title was Themes + <base> != love, but for some reason .Text doesn't seem to like it, and <base> would go away, instead of being htmlencoded or something, as would all other <foo> tags in the post, when doing an edit. Any ideas why? :)

Posted on Friday, May 5, 2006 11:52 AM | Back to top

Comments on this post: Themes + base != love

No comments posted yet.
Your comment:
 (will show your gravatar)

Copyright © Adrian Hara | Powered by: