Tuesday, March 6, 2012

Cleaning up that ugly client side aspx code


When managing a big web project, you might find yourself ending up with a big master page, that has a bunch of centralized code client side logic, like includes. What I mean by 'includes', is the part of the code where you spit out all the declarations for js and css files. I got to this stage many times by myself, and i've seen it happen at my various work places as well.

This usually ends up to some big nasty chunk of code that looks like this (and this is a relatively small example of what i mean...) :
<link rel="stylesheet" href="../../Content/bootstrap.css" />
<link rel="stylesheet" href="../../Content/common.css" />
<link rel="stylesheet" href="../../Content/widgets.css" />

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/bootstrap/bootstrap-dropdown.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/common.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/homepage.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/add-form.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/search-form.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/bookmark-list.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/register.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/openid.js")" type="text/javascript"></script>


Why is this bad ?
For starters, there's so much similar text here, that typing it all up should've ringed a huge bell for us, screaming "THIS IS WRONG!!".
The clutter of text here, bothers us from seeing what's really important here, and all that is, is the files being included here.

Why does this happen ?
The main reason for this is because we don't think of client side code as 'actual' code. This leads to us forgetting about DRYing up our code. The equivalent of this in server side code would be to copy the whole body of a certain method a dozen times, and just changing one parameter between different versions. If this were server code, we would've easily spotted the code duplication, and extracted this to a method that receives a parameter and saved a lot of typing, and kept the maintainability of the code.

How do we fix this ?
All we need to do is introduce a small helper method that will print this again and again for us. We can do this on the client and on the server. In this case, I would go with doing this on the client, just because this piece of code will probably only be useful for us in this specific context.

Here is my clean solution to this problem :
@{ Func<string, string> JsRequire = s => "<script src=\"" + Url.Content(s) + "\" type=\"text/javascript\"></script>"; }
@{ Func<string, string> CssRequire = s => "<script rel=\"stylesheet\" href=\"" + s + "\" />"; }

@CssRequire("../../Content/bootstrap.css")
@CssRequire("../../Content/common.css")
@CssRequire("../../Content/widgets.css")

@JsRequire("https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js")
@JsRequire("~/Scripts/bootstrap/bootstrap-dropdown.js")
@JsRequire("~/Scripts/common.js")
@JsRequire("~/Scripts/homepage.js")
@JsRequire("~/Scripts/add-form.js")
@JsRequire("~/Scripts/search-form.js")
@JsRequire("~/Scripts/bookmark-list.js")
@JsRequire("~/Scripts/register.js")
@JsRequire("~/Scripts/openid.js")


Sunday, March 4, 2012

jQuery relative position plugin - nextTo


The Problem :
I've already created quite a few jQuery plugins in the past, at work, and for personal use, and in many of them there are certain parts of code that always tend to repeat themselves.

One of these parts of code has to do with element positioning calculations relative to another element.
For example, when creating a plugin for a drop-down menu, or a tooltip, you can't avoid having a nasty piece of code in there, that all it does is calculate the element's position relative to the element we clicked on or hovered above.

I don't think there's any need for me to post an example of this, you probably know what I mean. This is usually the least most maintainable part of code in the plugin and the least easy to understand.

The Solution :
I finally decided to extract this ugly piece of code into a nice jQuery plugin that will hold all the dirty work calculations, and will leave you with a nice clean and understandable piece of code inside your plugin.

<scrip type="text/javascript">
    $(function() {
        $('.PutThisDiv').nextTo('.ThisOtherDiv', {position:'right', shareBorder:'top'});
    });
</script>


This plugin is hosted on google code : https://code.google.com/p/next-to/ (project name: 'next-to')
At the project page you will find more sample usages, usage explanations, the source code and a minified version.

Saturday, March 3, 2012

FireSheep version 2.0


FireSheep version 1.0
I think about two years ago I read about the FireSheep firefox plugin that allows you to hijack any user's account to many different sites (Facebook, flickr, twitter, etc.) that is surfing on the same wifi connection that you are using. This can be extremely brutal to use in any coffee shop, hotel, airport, just sitting outside someone's house stalking them, whatever...
The point is, the person who created this, Eric Butler, didn't do this as a hacking tool, but as a wake-up call to all the sites that aren't encrypting there connection via SSL, and a lot of them didn't even change that since...

FireSheep in action...

The potential danger
The second I read about this, I just couldn't stop thinking about what a dangerous tool this can become. Imagine this - Someone expands this tool to send all the currently active session cookies in the current wifi network to an online database, and now all the active sessions from all the firesheep users are shared worldwide. This means that you don't even have to be in the same wifi network as someone else to hijack their account. All you need is for someone else to be there while you're in the comfort of your own home... Isn't the internet a beautiful thing ??? :)

The future...
Two years (maybe more) later, and I'm happy to see that no one did this yet, but I am still very afraid of the day someone will!
I looked at firesheep code a little just out of pure curiosity, but never even downloaded it or tried it myself. I'm not a hacker and not interested in becoming one. The one thing I am concerned about here is my own personal security, so I am still hoping that these sites will improve the security for the sake of their users. Unfortunately, sometimes the only thing that speeds up the process is a lunatic taking advantage of the current situation.

Till then, beware...

Thursday, February 23, 2012

Unit Test looking for missing files in your project


When you're working with a big team of developers and a nice Build Server, a lot of times you rather work on a separate feature branch not to break the build while committing. This is very comfortable since you have your own "work zone" and don't bother anybody else, nor have to worry about breaking the build until you're done with your feature and ready to reintegrate to the trunk (or your main working branch).

But this comes with a price...
It's not always easy dealing with all the conflicts when reintegrating your branch, and sometimes this can lead to problems. One of the main problems we ran into a couple of times recently at my work place while doing this process was that while reintegrating, we missed some new files that were added to the project while dealing with the csproj file conflicts.

This means we had new files added to the project, and were in the project directory, but not in the '.csproj' file. This might be a class that is referenced throughout the project, which in this case you're lucky and the project won't compile, which will immediately let you know there was a problem. But if you're not lucky, this will be a controller class file, or an 'aspx' file, and leaving it out will never cause a problem for the build server (if your project isn't 100% covered with tests - a totally different subject for a whole new post!).

So... what's the easiest way to quickly solve this problem ? Write a test that will check this! :)
That's exactly what I recently did, and now every time this happens the build server will fail, with a nice message that shows you all the files you left out!
(of course, you need to make sure you didn't by accidentally leave this test out of the csproj!! :)

For your unit testing pleasures -

[Test]
public void CheckingThatAllFilesAreInCsProj()
{
    const string projectName = "TestWebsite";
    var projectDirectory = GetProjectDirectory(projectName);
    var projMissingFiles = RetrieveMissingFilesList(projectDirectory.FullName, projectName);

    Assert.IsTrue(projMissingFiles.Count() == 0,
        "There are files that are missing in the .csproj file : \n" + string.Join("\n ", projMissingFiles));
}

private DirectoryInfo GetProjectDirectory(string projectName)
{
    var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
    while (!currentDirectory.GetDirectories("*", SearchOption.TopDirectoryOnly).Any(x => x.Name == projectName))
    {
        currentDirectory = currentDirectory.Parent;
    }
    return new DirectoryInfo(currentDirectory.FullName + "\\" + projectName);
}

private string[] RetrieveMissingFilesList(string projectDirectory, string projectName)
{
    var csFiles = Directory.GetFiles(projectDirectory, "*.cs", SearchOption.AllDirectories);
    var aspxFiles = Directory.GetFiles(projectDirectory, "*.aspx", SearchOption.AllDirectories);
    var projFiles = csFiles.Union(aspxFiles);

    var csprojDocument = XDocument.Load(projectDirectory + "\\" + projectName + ".csproj");
    var csFileElements = GetCsFileElements(csprojDocument);
    var contentFileElements = GetContentFileElements(csprojDocument);
    var allFileElements = csFileElements.Union(contentFileElements);

    var projMissingFiles = new List<string>();
    foreach (var file in projFiles)
    {
        var stripFileName = file.Replace(projectDirectory, "");

        if (!allFileElements.Any(x => x.Attribute("Include").Value.ToLower() == file.Replace(projectDirectory + "\\", "").ToLower()))
            projMissingFiles.Add(stripFileName);
    }

    return projMissingFiles.ToArray();
}

private static IEnumerable<XElement> GetContentFileElements(XDocument csprojDocument)
{
    return GetFileElements(csprojDocument, "Content");
}

private static IEnumerable<XElement> GetCsFileElements(XDocument csprojDocument)
{
    return GetFileElements(csprojDocument, "Compile");
}

private static IEnumerable<XElement> GetFileElements(XDocument csprojDocument, string elementType)
{
    return csprojDocument.Elements()
        .Where(x => x.Name.LocalName == "Project").Elements()
        .Where(x => x.Name.LocalName == "ItemGroup" &&
            x.HasElements &&
            x.Elements().Where(t => t.Name.LocalName == elementType).Count() > 0).Elements();
}


The code in the test isn't the most beautiful thing I wrote but it does serve a great purpose.
All it does is search the project folder for all .cs and .aspx files, and then dissects the csproj file (which is just a big xml file) to find all the file references.
The code I posted just checks for cs/aspx files, but you can easily add functionality for js, css, html and any other file type you like...

Enjoy :)

Thursday, February 16, 2012

.net to Java transition gets a little easier for me...


I'm taking a university course in Java this semester, so I've been recently writing a lot of Java and as an IDE using IntelliJ (community edition) by JetBrains a lot. As a .net guy, mostly, I'm used to Visual Studio with ReSharper 6 and I remember so many keyboard shortcuts by heart which make my coding work so productive!

So you can guess how hard it is for someone like me, doing the transition to a different IDE, and not having ANY of the shortcuts you're used to. I tried studying some of the intelliJ shortcuts but it just got too annoying, and I finally decided to take the time and set ALL of the IntelliJ shortcuts to the same VS shortcuts once and for all. While I did that, I ran into a nice surprise - The brilliant guys at JetBrains were one step ahead of me the whole time, and have already added a VS keymap option in their settings panel!!!




Thank you JetBrains for making my Java experience just a little bit more comforting! :)

Saturday, February 11, 2012

VS Spell Check Extension - using Roslyn


A couple of months ago Microsoft published the Roslyn CTP which gives us an inside view on the Compilers view to our code. This also comes with project templates for creating CodeIssues and CodeActions (These are code suggestiongs/actions that are available to the coder in the IDE).

Since I read about this it interested me a little, and wanted to play around with this. Since I've been programming in java at home lately due to a course i'm taking at the university, I realized that one of the nice features that IntelliJ has is that it gives you suggestions on spelling mistakes you made on variable names (because this is one of the most annoying things i see in code and i truly believe makes it harder to maintain), so I thought i'd try to implement this in VS as an extension.

It was really simple to do so -

I just created a CodeIssue project :


With the ExportSyntaxNodeCodeIssueProvider attribute, you can tell it to execute the code only on variable declarations :


Split each variable name into separate words (most variables, at least when I write code looks like this "var myReceivedFilesList" so i separate them by case) :
public IEnumerable<CodeIssue> GetIssues(IDocument document, CommonSyntaxNode node, CancellationToken cancellationToken = new CancellationToken())
{
    var variable = node as VariableDeclarationSyntax;
    if (variable != null)
    {
        var nodes = variable.ChildNodes().Where(x => x.Kind == SyntaxKind.VariableDeclarator);

        foreach (var syntaxNode in nodes)
        {
            var fullVariableName = syntaxNode.GetFirstToken().ValueText;

            var wordsInVariableName = fullVariableName.SplitToWords();
  
            if (wordsInVariableName != null)
            {
                var correctSpelling = CheckAndCorrectSpelling(wordsInVariableName);

                if (correctSpelling != null)
                    yield return new CodeIssue(CodeIssue.Severity.Info, syntaxNode.GetFirstToken().Span, "Possible Typo ?\nMaybe you meant : " + correctSpelling);
            }
        }
    }
}


And viola!
You have the spell check feature on variable names in your VS IDE :



For the spell check I used the NHunspell project (This is the .net wrapper to the OpenOffice dictionary).

I put the code up on google code so you can take a look at it, and who knows, maybe even contribute to it... :)
https://code.google.com/p/gb-coding-extension/

I don't know if this is production-worthy code, I didn't even check performance or if it slows down the IDE. This was just a small learning experience for me.
Maybe if I have some more free time, and good ideas, I'll add to it more features in the future...

Wednesday, November 23, 2011

Compiling multiple projects into a single exe file in WPF


A long time ago I wrote a simple application using WPF (I will write about this utility in my next post) that I recently dug up from the lost archives and I wanted to use in my every day life (at work & at home).

I realized that this small application was made up of 3 projects, thus creating one exe file and 2 extra dll files.
Since I want to pack it light, and I truly see no reason to carry around 3 files that are all under 1MB, I looked for a way to compile all of this under one file.

After looking on the internet a little bit, I found a simple solution, which probably isn't the best way to do it but it works good enough for me...

First, in my main project, I created a folder called Assemblies, and put the other compiled dll's into this folder manually. Then, I defined these dlls' Build Action to be 'Embedded Resource' (this is found in the properties window of every file in your project - image attached).
This will cause the dll's to be compiled as resources embedded into the output exe file.



And now that the dll's are in the exe file, we can delete the dll's in our output folder and just run our exe file, right?
Wrong! The CLR will still look for these files in the folder (and also in the GAC) and when it doesn't find them it won't know what to do.

So all we need to do actually, is just tell the compiler where to look when it doesn't find the files in the original location.
This is done by overriding the method 'AssemblyResolve' in our current AppDomain object like this :

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
    {
        String resourceName = "MyProject.Assemblies." + new AssemblyName(args.Name).Name + ".dll";
        using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
        {
            if (stream == null) return;

            byte[] assemblyData = new byte[stream.Length];
            stream.Read(assemblyData, 0, assemblyData.Length);
            return Assembly.Load(assemblyData);
        }
    };

What we did here is just retrieve all the embedded resources and find the specific assembly the CLR was looking for.

Now, after compiling your project, you can delete the other dll files in your output folder and the exe file will work on its own.

While thinking of this solution, I didn't like the idea of having to copy the assemblies after every change into the 'Assemblies' folder I created, and then compiling again... but after thinking about it for a while, I think it's not that bad in my case if I consider the circumstances - I'm talking about a very small solution, only 3 projects, and all i need this packing into one file for is to move it around. I also don't believe I will be working on it that much more, so this means I just need to do this once. If it was a current project at work or even for fun, I wouldn't go with this option, and i would've found a better way around this...


An extra note : While running the application for the first time, it immediately crashed. I opened it in debug mode (which actually meant I needed to put a Thread.Sleep() in the initialization and then attach to process through VS since I wanted to delete the dll files before debugging). I realized that the application was looking for an assembly called XmlSerializers that I never created. I don't know exactly why, but it turns out that this was automatically generated while compiling. No worries though, this can be taken care of. Just go to the project properties > Build > Output > Generate serialization assembly = Off.