Tigraine

Daniel Hoelbling-Inzko talks about programming

dotless Presentation slides from Barcamp Klagenfurt

I just finished my presentation about dotless at Barcamp Klagenfurt and promised to upload my presentation slides to Slideshare.

The feedback for the talk was quite good. Turned out better than I hoped. I just hope that the slides do make some sense without me talking alongside.

.Less now supports files from the VirtualPathProvider!

Ok, I’ve just spent almost the whole day refactoring the hell out of our .less codebase just to add one tiny change:

Allow users to not only load files present on the current file system, but also directly from in-memory strings and VirtualPaths (as requested on the list). The problem here being that not everyone wants to serve his .less files right from the server’s file system but sometimes people have pretty sophisticated virtualized storage systems in place that require them to use the VirtualPathProvider abstraction that was added to .NET 2.0.
You can read up on that in ScottGu’s blog or David Ebbo’s blog, but in a nutshell it’s just another way to open files besides using System.IO.File.Open(), letting you forget about all the nasty stuff of where the file is really located. 

To do so I had to allow uses to plug in different “Sources” for .less code, and so I also had to make a breaking change to the main ILessEngine interface. The Interface was taking a filename as parameter, but in light of our recent support emails on the development list I decided that has to go away in favor of a more open approach (mainly to allow users to simply throw in-memory strings at the engine).

Because I know this will break some code, all implementors of ILessEngine still offer the old string parameter as an overload that then defaults to the default FileSource.

Now, for changing the source provider:

If you want to use anything besides the default filesystem based FileSource provider, you now have the ability to plug in a type implementing ILessSource through the DotLessConfiguration (thus through web.config).
.Less comes with three sources built in: VirtualPathSource, FileSource (default).

FileSource by default just opens a file through System.IO.File, while VirtualPathSource will use the HostingEnvironment.VirtualPathProvider.GetFile() method to open a Stream and read the .less code from there.

To enable the VirtualPathSource in your web application you simply need to modify your web.config a bit:

<dotless minifyCss="false" cacheEnabled="true" source="dotless.Core.VirtualPathSource">
  
</dotless>

The important part is the source attribute as it has to reference a type name implementing ILessSource. So if you want to create your own less source you could simply create another implementation of ILessSource and reference it’s name in the .less config.

If you want to use .less directly from your code to transform something you can just new up a LessSourceObject (the very output we get from ILessSource) and throw your code in there like this:

ILessEngine lessEngine = new EngineFactory().GetEngine(new DotlessConfiguration());
var output = lessEngine.TransformToCss(new LessSourceObject() {Content = "my .less code here"});

As always you can get the latest code from GitHub, or the latest binary release through our TeamCity build server. You can read more about .less (pronounced dot-less) on the project’s website at http://www.dotlesscss.com.


And while at it, we’d appreciate it if you spread the word about .less :).

Introducing: Tigraine.Logging

Stop rolling your eyes, I know there are more logging infrastructure libraries out there than there are projects using them. And I won’t say this one is different, it’s not. It’s more or less a little experiment I did to get accustomed to VS2010 and R#5.
Also note that most of the code originated from me writing a logging architecture for a Java OSS project I’m involved with and I wanted to carry the idea over to .NET.

But: I believe it turned out to be quite nice while very very lightweight. So I thought I’d just go ahead and share it.

Usage

Tigraine.Logging has a ILogger interface that exposes the usual suspects:

image

You just instantiate the appropriate ILogger implementation and are set to go, it will write everything you pass to it.

What makes out most of the code though is the ability to render objects passed into the logger as parameters. This idea came from the Java codebase where there was code like this scattered all over the place:

@Override
public String toString() {
	String ret = this.getClass().getSimpleName();

if (Config.logVerbosity >= Log.Verbosity.VERBOSE) { ret += "(" + this.hashCode() + ")"; } if  (Config.logVerbosity >= Log.Verbosity.VERBOSE) { ret += " A={" + this.a + "}, B={" + this.b + "}"; }

return ret; }

Now, I hate that sort of code. It’s just noise and it tends to get messy really soon. And so I started implementing my idea of ObjectRenderers (I know this term is already used by other logging frameworks, and the idea is not new either):

image

You add a renderer to the logger and whenever a object is passed in of the type, the renderer is invoked to transform the object to a string representation of your choosing. So instead of having to rely on .ToString() to give accurate results, you implement a class that takes care of writing all relevant information of your object down.

Here is a sample:

var consoleLogger = new ConsoleLogger(LogLevel.Debug);
consoleLogger.AddObjectRenderer<TestClass>(new TestClassRenderer());

consoleLogger.Error("Something went wrong with {0}", new TestClass());

The logging framework will call TestClassRenderer.Render to get a string representation of TestClass. This now also means you can have two different renderers, one verbose and one brief, and only hook up the one that’s right for you right now. The calling code does not need to be touched.

You can also define a renderer for a supertype and all subclasses will use that one if no more specific renderer is hooked up. If no renderer is found whatsoever .ToString() will get called.

And since implementing all renderers in their own classes would lead to a lot of code, there is a little helper class that should work for most of you by using some lambda syntax:

var compositeRenderer = new CompositeRenderer<TestClass>
    (p => p.Firstname + " " + p.Nickname + " " + p.Age);

Where to get

You may have already guessed, Tigraine.Logging can be found on GitHub and is open-source under the Apache License Version 2

Filed under net, programmierung, projects

Pandora used in dotless and moved to GitHub

Pandora, my personal IoC Container (mostly written for educational purposes) has recently been integrated into dotless. This has helped us improve the design of dotless without having to take on a big dependency like Windsor or StructureMap.

I chose to implement Pandora through the Common Service Locator interface by Microsoft, so if we ever feel restricted by Pandora we can easily switch to a more potent container without touching the actual dotless code.

This step also made me bring the Pandora repository from mercurial to git with some help from Horst. He was kind enough to run hg-fast-import for me.

Pandora can now be found on GitHub with a similar build process as dotless and elms-connector.

Pandora on GitHub

The joy of working with dotless

Ok, I just spent some time on the imagineClub website adding our board’s bio page. The HTML is not really interesting, but since imagineClub was written while dotless was still in development I wrote the CSS the old fashioned way.

Since dotless has reached some maturity I’ve been dogfooding it on imagineClub to make use of the minifier and the caching, but never had any real LESS code in there.
When I had to fix something today I was so happy to be able to write CSS like this:

div#team
{
    width: 414px;
    p
    {
        float: right;
        width: 300px;
    }
    h2
    {
        clear: right;
        font-size: @title-fontsize - 4;
    }
    img
    {  
        width: 100px;
        margin-bottom: 4px;
    }
}

This is how CSS was supposed to be, and with dotless it has become just mindlessly easy to do..

ELMS-Connector documentation available

I decided not to invest any work in writing docs for a tool only I am using, due to the fact that it quite rapidly outdates during active development.

Well, ELMS-Connector development is mostly finished and after getting an email by someone from Amsterdam asking how to use ELMS-Connector I decided to finally write the docs.

The documentation is in the GitHub repository alongside the code, but I also saved it as PDF and uploaded it.

It’s by no means perfect, but it should be enough to get anyone who wants to use ELMS-Connector up and running quite smoothly. Comments are always welcome.

EMLS-Connector v1.0 RTW

After almost a month and 3 weeks of having the connector in production I finally feel that it’s time for a v1.0. So, here it is. I just pushed the v1.0 tag to GitHub!

You can grab the release zip containing everything you need here:

ELMS-Connector v1.0 RTW

Note on this release: Some of the existing code I published in my initial article is now outdated. Some refactoring (and a annoying typo) has gone on and I don’t have any docs ready for people trying to use this. So if you want to use ELMS-Connector on your campus, just contact me through email at [email protected] and I’ll be glad to walk you through the setup process. Docs will follow, but at the moment I don’t feel like writing documentation for something only I am using.

Changes since the Beta:

1: Configurable file extensions

2: Session Authentication

Session Authentication

The main annoyance with ELMS-Connector so far has been that whenever a User hits the MSDN-AA he has to re-authenticate himself even if he is authenticated to the source system.

I found a way to elegantly prevent that without breaking anything: IExtendedAuthenticationService

While IAuthenticationService only requires you to implement one method:

bool AuthenticateUser(string username, string password);

IExtendedAuthenticationService comes with another two:

public interface IExtendedAuthenticationService : IAuthenticationService
{  
    bool IsAlreadyAuthenticated();
    string Username { get; }
}

IsAlreadyAuthenticated should return true if the current user already has a open session, and Username should then return his current username. If you use IPrincipal in your web app this would look like this:

public bool IsAlreadyAuthenticated()
{
    return HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated;
}

public string Username {     get     {         return HttpContext.Current.User.Identity.Name;     } }

This way ELMS doesn’t prompt the user again for his credentials but rather directly redirects him to Microsoft’s ELMS server, making for a very smooth user experience.
If IsAlreadyAuthenticated is false, the user is presented with the usual login form and authentication works like it used to before (this happens if the user comes from the Microsoft ELMS site without having a session on your campus site).

Setting up TeamCity + git + psake for dotless

Let me say one thing upfront: Setting this up has been a HUGE pain in the ass (PITA for short), and I really hope this gets fixed sometime in the future, because those 3 hours I just spent getting this done are never coming back..

Ok, just to make sure everybody understands: dotless is built using a PSake build script that has to be run through Powershell. The script itself calls out to git and therefore relies on git being installed into the PATH.

First: Git-Teamcity

Since our build relies on executing a git command during build the official JetBrains plugin doesn’t cut it (it only copies the sources, not the .git folder). So I downloaded git-teamcity from GitHub and built it using maven (at least something worked).

After that I followed this tutorial on how to install the plugin on TeamCity:

  • package the plugin by following the steps outlined in file pkg in the Git plugin folder: create a foldergitAgent/lib in the folder target, copy all the .jar files (should only be Git-vcs.jar) to this folder, and then zip gitAgent to gitAgent.zip
  • deploy the plugin by following the steps outlined in file deploy in the Git plugin folder: copygitAgent.zip to \webapps\ROOT\update\plugins, and copy Git-vcs.jar to\webapps\ROOT\WEB-INF\lib

Well, after setting up a new VCS Root inside TeamCity the most important part is to set the VCS checkout mode to “Automatically on agent (if supported by VCS roots)”

image

Warning: Also make sure that you have git installed at C:\Program Files\git, because that is the only place git-teamcity will look for the bin (unless you change the code).

Second: Execute Powershell

Apparently there is some major bug with the ConsoleRunner inside TeamCity so all attempts to simply run the Powershell didn’t work. Directly invoking Powershell led to the build timing out. After some digging I found this thread that explained the problem and hinted at a possible solution: Touble with Powershell and NAnt during build

So, I created a .bat file called TeamCity.bat that calls Powershell directly from it’s full path (C:\Windows\System32\…) like this:

C:\WINDOWS\system32\windowspowershell\v1.0\Powershell.exe .\psake.ps1

But this doesn’t work due to the above bug in TeamCity. The build kept hanging and eventually got terminated due to an timeout. So I had to change it to something like this:

echo abc | C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe .\psake.ps1

Putting echo in front of it made it work, I have no idea why, but id worked.
Now the next problem came up: although I explicitly ran Set-Executionpolicy on the box the runner’s executionpolicy was not set. So I added the Set-Executionpolicy to the .bat file:

echo abc | C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe Set-ExecutionPolicy remotesigned
echo abc | C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe .\psake.ps1

Now, finally the script was executing, but due to no environment variables, my buildscript could not locate git (due to the ConsoleRunner not having ANY environment variables present).

The final version of my TeamCity.bat then included a change to the PATH variable and it finally worked:

Set "path=%path%;C:\Program Files\git\bin" 
echo abc | C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe Set-ExecutionPolicy remotesigned
echo abc | C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe .\psake.ps1

At that point the build was finally executing and I then only had to tell TeamCity where to find the build artifacts and I was done.

Conclusion

Now that it works, I’m glad I took the time to set it up. But the process could have gone smoother.
Anyway, the good news is:

You can now get a release version from every future commit to the dotless repository right from our dotless TeamCity server!

imagineClub.at is now finally online

logo After almost 4 months of work I am pleased to announce that the new imagineClub Website is finally online at

http://www.imagineclub.at

You can read what this is all about here.

Besides the obvious design refresh the new website has numerous administrative improvements that allow us to more easily share information with members and also allow new members to join the fun since we are now able to unlock their accounts without having to hack SQL together.

As you may already know, the new website is also licensed as open-source software and the code is freely available from my GitHub Repository. Since we allow our users to use MSDN-AA the site internally uses my other open-source project elms-connector (source on GitHub) to connect up to the Microsoft servers.

And to take dogfooding to a new level, I already have a unpublished changeset that will make imagineClub.at use the dotlesscss project to improve the project's CSS.

You may have guessed by now that the whole site is completely built ontop of open-source frameworks. It is based on Castle MonoRail, running ontop of Castle ActiveRecord with some (but not deep) Castle Windsor integration.
In fact, I would have used Windsor more, but using the ActiveRecord pattern with all it's static goodness somehow limited the use of inversion of control.

I primarily chose Castle MonoRail due to the fact that I had come off a ASP.NET MVC project and wanted to learn another MVC framework besides the blue one. I can't say I'm sorry for that decision. MonoRail has proven itself to be a very mature and very extensible framework that supported me all the way to releasing the site. 
I do regret however chosing NVelocity as my viewengine, Spark seems to be the better choice at the moment and NVelocity is really awful when it comes to debugging problems.

Anyway: Thanks to all these great open-source projects that made this possible, and also a big thanks to Kristof who sponsored the new design!

ElmsConnector configurable file extension

Seriously, nothing makes you more aware of problems with your stuff than dogfooding! I’ve been busy all day trying to get the new imagineClub website out of the door (yes we finally launched!) and just when I thought I had everything nailed one thing about ElmsConnector made me panic:

IIS6 is not passing *.elms requests on to the ASP.NET pipeline, so ElmsConnector was never called.

To fix this you need to have access to the server configuration and change that through IIS Manager. Since we (and I guess many other people) are on a shared host we could not do that, and so I had to change all paths to *.axd on short notice.

But, I felt like *.axd may also not work for everyone, so I decided to just make that an optional setting through the elms.xml:

<component id="FileExtensionProvider">
  <parameters>
    <extension>ashx</extension>
  </parameters>
</component>

This little XML will change all paths inside ElmsConnector to .ashx instead of the default .axd. (Omitting that XML will result in all your paths being .axd)

Also note that I had to introduce one additional placeholder into the Login.htm.


Make sure that you include the $EXTENSION$ placeholder into your form action:

<form method="post" action="VerifyUser.$EXTENSION$">

This feature is available through release v0.1.0.3 from GitHub.

My Photography business

Projects

dynamic css for .NET

Archives

more