The configuration of the module is a descendant of any EPiServer Virtual Path Provider configuration. This aspect is fairly well described on EPiServer pages.

A sample configuration for the TextImageVirtualPathProvider can look as follows

<configuration> <episerver> <virtualPath <providers> <add showInFileManager=false virtualName=Text Images virtualPath=~/TextImages/ bypassAccessCheck=false name=TextImages type=Cognifide.ImageVirtualPathProvider.TextImageVirtualPathProvider,Cognifide.ImageVirtualPathProvider physicalPath=C:\temp\TextImages allowedReferers=(localhost) allowNullReferrer=false replacementStrings=$colon$,:,$gt$,>,$dot$,.,$quot$,&quot;,$amp$,&amp;,$star$,*,$eol$,&#10;,/> </providers> </virtualPath> </episerver> </configuration>

 

where:

  • physicalPath is where the cached version of images will be stored
  • shownInFileManager is “false” as there is nothing to present for the user in the file manager.
  • allowedReferrers is the regular expression containing the filter for sites that are allowed to access the path provider and get images. This has been added so that your server does not turn into the internet’s text-image open service :)
  • allowNullReferrer should be set to false in production environment but allows for testing by directly creating URL’s without using a page to fill in the referrer.
  • replacementStrings – this one actually turned out to be very useful since some characters are invalid and not even reaching the VPP if EPiServer or ASP detects them. so to allow for characters like colon or < or even a dot (which would make it hard to form regular expression if it was explicitly available) or * you need to create an escape token for them. The string is a coma separated list of token,value,token,value,…
  • virtualPath is something you need to change if you want your VPP to serve images under a different root level folder. (e.g. if you have a page with that name already)

 

Additionally for IIS6 (most common scenario) you need to add <location> node to configuration for the VPP to work.

<configuration>
  <location path=TextImages>
    <system.web>
      <!– Setup the StaticFileHandler for the wildcard mapping to work in IIS6–>
      <httpHandlers>
        <add path=* verb=GET,HEAD type=System.Web.StaticFileHandler validate=true />
      </httpHandlers>
    </system.web>
    <staticFile expirationTime=-1.0:0:0 />
  </location>
</configuration>


Unless you want to change the location of the virtual path provider can be found under, there is nothing you need to change here.

The code is accessible on EPiCode, but you can also download a compiled binary here. All you need to do then is to unzip the archive to the “bin” folder within your site and set the web.config values to your preference.

Popularity: 33% [?]

The module code is already available on Epicode SVN, the relevant wiki pages will be following as soon as documentation is complete.

The use case is as follows:

  • The client wants the site to look exactly as in a template provided as a image,
  • the text is using a non standard font that is not available on 60% of Windows machines,
  • the site does not use flash.
  • the site needs to be equally good looking in IE6 (more about it later)

The solution was to generate images, but how to do it the right way? This has presented us with a once-in-a-lifetime :) opportunity to create a virtual path provider, do something good and learn something new & cool in the process.

Creating a new virtual path provider.

this functionality in itself is fairly well documented on MSDN one thing to pay attention to is to remember to pass the control to the next provider in the provider queue if your provider does not want to serve the request, so in my case:

public override VirtualFile GetFile(string virtualPath) { if (IsPathVirtual(virtualPath)) VirtualFile file = new TextImageVirtualFile(this, virtualPath); return file; else return Previous.GetFile(virtualPath); }

this is necessary so you don’t have to have all-or nothing solution (your provider either serving everything the user requests or not being accessible at all) and honestly I’ve spent quite a while before I found out that… I was just being silly – thinking the technology by itself will resolve that ;)

If your Virtual path provider does not actually implement directories you don’t have to make the very provider to do a lot of complicated things. you are perfectly fine to limit the implementation to providing a custom constructor so that EPiServer passes you the configuration data and a couple of methods to tell whether a file is what you want to handle or not

// this one is actually really cool - whatever values you set in your web.config // will be passed to you in the collection so you can really make your VPP
// as configurable as necessary public TextImageVirtualPathProvider(string name, NameValueCollection configAttributes)
// This one resolves if the file can be generated public override bool FileExists(string virtualPath) { /* … */ } // Pretty much only passes the info that directory was not found // found if the virtual path matches a path that we should handle public override bool DirectoryExists(string virtualDir) { /* … */ } // Retrieves the virtual file that generates the image if the // Virtual path matches our pattern or disregards the request if it doesn’t public override VirtualFile GetFile(string virtualPath) { /* … */ } // Again this is only a pass through method as we don’t support directories public override VirtualDirectory GetDirectory(string virtualDir) { /* … */ }

Now that we have ASP passing the request to us we need to wonder how to format the request in a way that is intuitive to the user, I wanted the URL to be straightforward and follow the path of EPiServer’s friendly URL-S so that they are easily formed by editors. So how about:

http://my.server.com/color/font-name/font-size/The%20text%20i%20want%20to%20print.gif

Ok.. well…, that won’t fly for GIFs - the font will be plain ugly if I don’t use antialiasing and if I do I will have an ugly black background underneath it. The solution to that would be using translucent PNG (which the VPP supports) but IE6 does not support those with transparency without ugly hacks. So I need to replace the blacks with a hint so that it generates a background colour when it merges the background with the font for antialiasing. For the sake of this article let’s assume it was an easy switch (IT WASN’T!) and let’s extend the URL to:

http://my.server.com/color/antialias-hint-color/font-name/font-size/The%20text%20i%20want%20to%20print.gif

But I need the font to be bold! Ok… ok…

http://my.server.com/color/antialias-hint-color/font-name/font-size/font-formatting/The%20text%20i%20want%20to%20print.gif

Can I have the image rotated too? Sigh….

http://my.server.com/color/antialias-hint-color/font-name/font-size/font-formatting(optional)/transformatio(optional)/The%20text%20i%20want%20to%20print.gif

The image rotation follows the RotateFlipType enumeration so you can specify any string that is defined in the MSDN documentation for the enumeration.

A sample result for the URL:

http://my.server.com/TextImages/Blue/white/Courier%20New/40/BUI/rotate270flipnone/Hello$eol$from$eol$Cognifide!.gif

Will look as follows

Hello$eol$from$eol$Cognifide! 

For the curious

The final string format matching regular expression looks as follows:

Regex regex = new Regex( @"^(?<colour> # The first match - starting form the beginning of the string
([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[a-zA-Z]*)) # match either a 6 hex digit string or a name of a known color - this is for text color / # now we expect the first separating slash (?<hint> # next match group is about background hint for antialiasing ([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[a-zA-Z]*)) # match either a 3 or 6 hex digit string or a name of a known color - this is for antialiasing color hint / # again separating slash (?<font>[\w\s]*) # font family name - accept white spaces / # yet another separating slash (?<size>[\d]{0,3}) # font size / # oh noes! another slash! ((?<style>[BIUSRN\s]*) # font style Bold, Italic, Underline, Strikethrough /){0,1} # this group is optional. ((?<transform>[\w]*) # transformation name as specified with System.Drawing.RotateFlipType - this group is optional /){0,1} # this group is optional too. (?<text>[\s\S]*[^\.]) # the text to render - basically anything but a dot - use relacement strings for dots [\.] # separating dot - now that’s a nice change! (?<extension>(png|gif)) # the file extension - so that we know whether to generate png or gif $ # everything comes to an end ", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.CultureInvariant);

 

Usability concerns

The Colours can be provided as both named Colours (red, green, etc..) or html hex formatted colours (e.g. ff00bb, fob, fff, badfoo) both 6 and 3 hex digits strings are accepted.

The URL accepts spaces, and whatever text string that cannot be passed as a part of the url or is invalidated by EPiServer can be escaped by defining a token for it in web.config so for example as you can see in the above url the end of line “\n” character has been escaped into $eol$.

Obviously the font selection is limited to what is installed on your server.

Performance concerns

The basic concern that comes to mind is – how does this impact the server performance if the image is generated every time? Even though the performance impact seemed to be negligible I’ve decided to cache content. These things simply pile up if you have a high load site so why take the chance? Once an URL is called it is saved on first generation asserting the uniqueness of each parameter. Colours like black and 000 will be treated as same colour and cached only once.

Security concerns

So what was done to prevent our server to be an open server for generating images for everyone on the Internet? The VPP only allows for the images to be generated if the request referrer is in a domain or a host that is specified in the web.config. Additionally for testing you can enable the referrer to be null (direct call to images, as opposed to referring to them from a page).

Also as a seconds line of defence, it’s wise to define the cache folder on a share with a quota so we don’t get our server filled up with images should the referrer limiting measure fail for some reason.

Popularity: 36% [?]

CogniScale - virtual hosting made easy

We’ve not been talking much about it and that’s partially my fault as well (busy with other projects), but Cognifide has a really cool initiative called Cognifide Labs that we intend to grow over time. The plan is to devote up to 10% company time into side projects that help us grow expertise and allow our devs to dwell into interesting technologies, methodologies and languages and develop their skills.

One of the first projects (that I took part in) is CogniScale - an app that allows FlexiScale users to manage their servers. Here’s the story…

Being the agile company taking part in many EPiServer projects we never seem to have enough environments to test our web-apps and software in general in various scenarios. We find ourselves constantly reinstalling and trying to keep our servers in a state that can can at least remotely be called as stable. After all how many deployments and tearing down of various EPiServer, CruiseControl, TeamCity, SQL Server and other "I need to have" apps can a server take before slowing down to a crawl or collapsing all together (that said I bow before our faithful THOTH for taking all the abuse it does). We definitely needed more servers! And we needed them now!

Early this year we’ve started to talk to the guys at XCalibre that came up with a great idea. What if you could have an unlimited amount of servers available for you at any given time? I mean really what if you could have 0 servers one day and the next day have a rich farm of servers for literally no cost, paying only when you power them up and not paying a bit if you take them down.  This turned out to be quite a project for them that turned to materialize as FlexiScale. (you can read more about it here). Looking at all that I’ve mentioned before while eliminating the cost of maintaining the servers locally we decided to give FlexiScale a spin.

Read the rest of this entry »

Popularity: 45% [?]

Is EpiServer a hard-shelled clam or what?

As much as I seem to be enjoying my trip with EpiServer there are some little things I don’t seem to appreciate all that much and I’m not quite sure how to work around some of them in an elegant way.

EpiServer has a fairly advanced way of dealing with properties but it also seems to be a bit tough on the developer whenever you try to do something more than just strictly using its API-s. One of the areas I don’t really enjoy is the dealing with the pages that are expired or generally unavailable for the user for various reasons.

In the project that we’ve been implementing recently we needed to store page ids for further reference in numerous places and although this generally works, accessing a page that’s been deleted, expired or not published yet, has proven to be a challenge and I can’t seem to be able to find an elegant solution around it.

For instance, we have a list of bloggers, that are stored in our faceted navigation with links to their pages, our system lists them and the links to their pages, should someone’s page be unpublished yet - we run into problems.

Another good sample of where this is needed is a list of pages (A multi-page property of sorts). There seems to be no implementation of a multi-page property in EpiServer and the only reasonable implementation that I’ve been able to find is available through EpiCode. The following is it deals with the pages going in or out of the system, which leads me to think that the only way of checking whether a page is available for me is to instantiate it with all the consequences of it:

// get the page with error handling for // access denied or deleted page try { PageData page = Global.EPDataFactory.GetPage(pageref); isExternalLink = (page.StaticLinkURL != multipageLinkItem.Url); if (page != null && isExternalLink == false) _selectedPages.Add(page); } catch (PageNotFoundException notFoundEx) { // We should not add the page if it // does not exist } catch (EPiServer.Core.AccessDeniedException accessDeniedEx) { // User is not allowed to see page, skip it } catch (Exception ex) { // The page could not be loaded, for some other // reason. System.Diagnostics.Debug.Write(“Page could not be loaded: “ + pageref.ToString(), “PropertyMultiPage”); }

What I do not like about this part (of an otherwise remarkable piece) of code is that exceptions are not supposed to be the driving force of the program flow. But in this case they seem to have been forced to do it. It’s like I had to open a file to check its size or whether it even exists.

I can see why the system will not let me visit the page if I’m not allowed to do it as a user, but the fact that the API frowns at me whenever I even try to instantiate it just to check its existence or my rights to it has proven to be quite problematic. After all a user is not supposed to see a login screen in the list of pages, but rather when he/she enters a page that he/she no no rights to. Better yet, give me a way to check whether I even can access it.

Is there one already? Has anyone heard? Did anyone see?

Popularity: 76% [?]

Common Language Runtime, now even more common

There seems to be a storm over at over at the Internet about Microsoft going Cross platform and “opening the common language runtime to a multitude of platforms”. What seems to be a false perception that even such respectable podcasts as Buzz Out Loud or even TWIT fail to realize and mislead people on is that this has NOTHING to do with portable .Net desktop applications. Someone even suggested at one of the BOL podcasts that it’s Microsoft’s attempt to put .Net Framework on Linux servers. (Huh? Beg your pardon?) You may have not noticed it but when they say about cross-platform capability of Silverlight it always says Windows, Mac.. and then on a single breath they start enumerating browsers. A casual listener just measures the quantity and the list has an impressive 5-6 bullets. heh… wait… erm… not really… it’s actually only 2 platforms. You cannot enumerate browsers as platforms! You share 99% implementation between them, the only cross-browser thing is the interaction between the plugin and the host browser!

As a .Net developer this pretty much makes me laugh through tears. What an excellent publicity stunt. First of all, Microsoft does not plan to release a Linux version. It’s cross-platformedness (is that a word?) refers strictly to the fact that there has been a runtime engine port made for a Mac. What was ported? The CLR and the DLR. Big deal! This has been there in a form of Mono years ago! And the CLR is available for Linux for a few years now. How is that suddenly an exciting thing?

If you’re interested in what exactly was done you may want to look at the interview with Scott Guthrie, GM of the Silverlight team. GAC was not ported. Wait! GAC WAS NOT PORTED?! Only a subset of classes that are needed inside a browser. Basic GC, no ASP.Net. It’s nothing like a cross platform version of a full .Net framework. this is also nothing really that new from the cross platform point of view - this kind of stunt was already pulled by Microsoft in form of the Compact version of the .Net framework. Something similar has already been done in terms of XNA - which is a form of .Net framework for XBox. In fact Silverlight is much more like XNA than it is like the full .Net framework.

Second of all the only open part is the DLR which is actually developed in an “embrace and devour” fashion. Ruby, Python and the likes developers - we love you! come join us under our Common Language runtime! Of course Microsoft will open it. Those developers are all about open and free this makes a lot of sense doing it this way. Give something, get a lot in return. Don’t get me wrong, I love the dynamic extensions, and I really like what’s being developed in the DLR, but make no mistake, the motives haven’t changed.

In the end CLR has been open for a long time and it’s not where the most exciting part of the development is. It’s the framework. I’ve not seen a word about Windows forms being ported. Or any of the ASP.Net namespaces on that mater. Heck even Mono has big ASP.Net 1.0 and chunks of 2.0. If you look at the image where do you see the CLR?

It’s the small middle circle inside the big one. That’s a far cry from releasing .Net as a standalone portable framework. And if you think about it, it does not make any sense from Microsoft’s point of view to go the whole way. What for? for it to make Windows expendable? Ridiculous!

My feeling is that (other than making another bucket of money), partially the motives behind is is to kick Adobe’s butt. If it did not occur to you yet, Microsoft and Adobe are full-out at war at this point. PDF is combated with XML Digital Paper, Flash has its Silverlight, Shockwave (& Macromedia Director) has Blend and XAML now and so on…

Adobe already takes shots back at Microsoft

While Adobe made PDF readily-available to other software companies such as Apple, Sun, Corel, and OpenOffice, when it came to deep-pocketed Microsoft, Adobe took a different stance, demanding that it remove the feature and charge a separate fee.

In response, Microsoft agreed to remove the feature, but refused to charge consumers separately for it. Adobe consequently sought negotiating leverage by threatening to sue before the EC, despite the fact that neither Adobe nor Microsoft are based in Europe, neither operates major production facilities there, and neither maintains primary business locations there.

Now that we have a few myths busted, I don’t want you to think that I am not excited by Silverlight.

The coolness ensues

It is still incredibly cool that they are doing it and not for the cross platform reasons (although it’s nice), and not for the multi browser compatibility (even nicer), but for it’s roots in the full framework. For us .Net developers it’s like one day we woke up and we knew how to write Action Script (Flash) applications. The Silverlight download is only 5 meg, so in the broadband world it’s going to be on almost every computer fairly quick. We will have a robust development environment for developing those applets in less than a year. It’s root in the .Net framework roots will make it talk seamlessly to our IIS embedded apps and services. You wanted web applications?

You asked for web applications? We will deliver…
… only they will be desktop applications running inside a browser we approve....
… and on any platform we choose for you…
the best of both worlds - no matter if you want to run them in Windows OR in Internet Explorer. :)

But honestly - should you use some artificial and clunky surrogates of instantly-responsive-interactivity in forms of AJAX when you can have the real thing running faster and delivering much wider functionality? Developing a browser apps was possible before, but .Net was never perceived as a platform specifically designed for that kind of activity, the quasi multi-platform/browser compatibility has a chance to change that perception. Perfect crime :)

I can’t wait for Silverlight to turn gold. It’s a brave new world.

Popularity: 80% [?]

Posted in .Net Framework, C#, Internet Information Services, Rants, Software Development, Web applications
3 Votes | Average: 3.67 out of 53 Votes | Average: 3.67 out of 53 Votes | Average: 3.67 out of 53 Votes | Average: 3.67 out of 53 Votes | Average: 3.67 out of 5 (3 votes, average: 3.67 out of 5)
Loading ... Loading ...
| No Comments »

I’ve recently been asked by one of our new dotNet developers whether it’s possible to cast your regular everyday .Net 1.x System.Collections.ArrayList or the like onto a generic System.Collections.Generic.List<T> . I have to admit, I seem to suffer from some kind of Obsessive-Compulsive Disorder when it comes to programming problems. I mean my original reaction is usually “Of course not, what kind of frivolous idea is that?“, but then I cannot go about without solving the problem. So it was this time.

There seems to be no pre-coded framework solution for the problem, you should iterate over the items instead.  

At first I thought we could make use of the the framework supported conversion of  List<T> into List<Y>through a somewhat awkward method in the List<T>

public List<TOutput> ConvertAll<TOutput> (
	Converter<T,TOutput> converter
)

which requires you to implement a delegate that will do the conversion for every item. One problem with this solution though is that it does something exactly oposite to what we needed. It exports rather than importing and it does so between two generic types. However, there is an easy enough way to add this functionality in and you will only need to code it once and you will probably want to place it in some kind of static utility class.

 public static void copyToGenericList<T>(IEnumerable list, IList<T> genericList)
{
    foreach (object o in list)
    {
        genericList.Add((T) o);
    }
}

With the help of this method you will copy any enumerable type into whatever generic list you may find. Granted the method is not doing any type checking and will fail in case of any type mismatch it may encounter, but you would want to know about it nonetheles, wouldn’t you? Simple try/catch it around will do the trick, either that or a simple modification: 

public static void copyToGenericListChecked<T>
    (IEnumerable list, IList<T> genericList)
{
    foreach (object o in list)
    {
        if (o is T)
        {
            genericList.Add((T)o);
        }
    }
}

Which however will fail silently if the objects in the original list are of a wrong type, which in turn makes using it quite dangerous.

The copying now becomes quite effortless:

//Create a non generic list of type in with some data in it
IList list = new ArrayList();
list.Add(456);
list.Add(123);

//our generic target
IList<int> intList = new List<int>();

//and the copy routine - completely effortless
SomeUtilClass.copyToGenericList(list, intList);

But better yet, why not simply create the list of the type you expect and populate its contents in one go from the non-generic? Sure:

public static List<T> convertToGenericList<T>(IEnumerable list)
{
    List<T> result = new List<T>();
    foreach (object o in list)
    {
        result.Add((T) o);
    }
    return result;
}

And the sample usage becomes exactly what we hoped for:

//Create a non generic list of type in with some data in it
IList list = new ArrayList();
list.Add(456);
list.Add(123);

//and the one line conversion - nice!
IList<int> intList2 = SomeUtilClass.convertToGenericList<int>(list);

Generics rule!

Popularity: 48% [?]

Posted in .Net Framework, C#, Software Development
 Votes | Average: 0 out of 5 Votes | Average: 0 out of 5 Votes | Average: 0 out of 5 Votes | Average: 0 out of 5 Votes | Average: 0 out of 5 (No Ratings Yet)
Loading ... Loading ...
| 1 Comment »