Schedule for Øredev 2010

Posted on 8 November 2010 and tagged with , 4 comments

The yearly Øredev Developer Conference is now closing in, and I’m really excited to be able to participated this year. I’m leaving Wednesday and getting there around 10-11 AM which means I will unfortunately miss a few sessions in the morning but I’m sure the other sessions will weight up.

I look forward to learning a lot of new interesting techniques and patterns, especially in sessions covering .NET, web app development, HTML5/CSS3 and nosql. It will also be great to see people like Jon Skeet, Brad Wilson, Jeremy D. Miller and Jonathan Snook “in real life”. Makes me wonder if Jon Skeet will even answer questions now when he can’t get any up-votes for it?

The sessions I will attend to are:

Wednesday

  • 11:20: ASP.NET Web Matrix and Web Pages, Brad Wilson
  • 13:10: Patterns for Building Internal DSL's in C# 3.0, Jeremy D. Miller
  • 14:15: Better Practices for Building Fast Web Apps, Giorgio Sardo
  • 15:35: Automated Testing of Web Applications, Jeremy D. Miller
  • 16:40: CSS3, Jonathan Snook

Thursday

  • 10:15: Higher-Order JavaScript, Giles Bowkett
  • 11:20: Exploring Windows Phone Dev, Jeff Wilcox
  • 13:10: CouchDB for .NET Developers, Hadi Hariri
  • 14:15: ASP.NET MVC 3, Brad Wilson
  • 15:35: Abusing C#, Jon Skeet
  • 16:40: Compositional Design with Responsibility Driven Design, Jeremy D. Miller

Friday

  • 10:15: My last 30 failures, Ted Valentin
  • 11:20: C#'s Greatest Mistakes, Jon Skeet
  • 13:10: 19 1/2 Things to Make You a Better Object Oriented Programmer, Greg Young
  • 14:15: Top 20 tools and tips that make me a better developer, Roy Osherove
  • 15:35: Pluggable web applications, Rob Ashton

= me like.

Read More »

“Key has already been added” exception with PageTypeBuilder

Posted on 7 October 2010 and tagged with , , 3 comments

This is one of those exceptions you get and you know you have had them before but never remember the solution, and googling them doesn’t give you any answers. Time to fix that!

Background

I was in the process of creating lots of new page-types for a new EPiServer  website and suddenly it threw an exception after building and running the site. The exception message I got was “An item with the same key has already been added.” with the following Stack Trace:

[ArgumentException: An item with the same key has already been added.]
   System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) +56
   System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) +10290303
   System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) +12
   PageTypeBuilder.PageTypeResolver.AddPageType(Int32 pageTypeID, Type pageTypeType) +52
   PageTypeBuilder.Synchronization.PageTypeSynchronizer.AddPageTypesToResolver(List`1 pageTypeDefinitions) +159

What we can understand from the above Stack Trace is that when PageTypeBuilder adds a new page-type to the dictionary it fails because another item with the same key already exists. My colleagues and I were determined this key must be the page-type GUID that you specify in the attribute of a page-type. I opened the database and deleted all page-types directly, and then changed the GUIDs in my classes. This has to work – but it did not.

Solution

I gave up and continued working with my page-types. After a few minutes I found a page-type with an incorrect name – it was a duplicate of another page-type! I changed it to the right name and ran my site. Everything worked! I had been affected by the “copy-paste error”.

To sum it up: Every page-type must have a unique Name property or else it’ll fail in runtime.

It would be nice if PageTypeBuilder threw a friendly exception if the key already exists. If the exception message also mention which page-type (by ID or name) it would be really easy to find and solve the problem.

Maybe it’s time to submit a patch to the PageTypeBuilder project?

Read More »

Import Namespaces for Razor Views

Posted on 28 July 2010 and tagged with , 0 comments

Previously when developing with the WebForms view engine we could use the Web.config file to import namespaces where we stored our extension methods or models. They would then be available to all our views without having to explicitly declare them in each view.

In Razor this is no longer possible due to how it’s built, which is why we have to manually register them in the Application_Start event.

To do this begin with opening Global.asax and create a new method called RegisterGlobalImports, and call it from the Application_Start method. In the newly created method you add all the namespaces you wish to have in your view by calling AddGlobalImport on CodeGeneratorSettings.

public static void RegisterGlobalImports() {
    CodeGeneratorSettings.AddGlobalImport("MvcApplicationRazor.Core.Extensions");
    CodeGeneratorSettings.AddGlobalImport("MvcApplicationRazor.Core.Models");
}

protected void Application_Start() {
    RegisterGlobalImports();
    
    AreaRegistration.RegisterAllAreas();            
    RegisterRoutes(RouteTable.Routes);
}

I usually register extension methods, that should be available in the view, and models so I won’t have to type namespaces over and over again.

Read More »

Getting HTML Colorization with Razor View Engine

Posted on 27 July 2010 and tagged with , , 0 comments

imageToday the Gu announced the first preview of ASP.NET MVC 3, which included the new Razor view engine. I’ve been really excited about it as I feel it makes our views a lot prettier than before with Web Forms view engine. It will also be a lot quicker and smoother to type without all those messy <%-characters.

To the point! I am currently upgrading an existing site to use MVC 3 and Razor. However in this first preview of MVC 3 we won’t have any File Colorization or IntelliSense in .cshtml files. This means it will look like we’re editing in Notepad. It got me wondering if there was a way to at least get some colorization, more specifically HTML colorization. I wandered around in the options of VS2010, and eventually found the place where I could map an extension to a different colorization.

This is how you get HTML colorization in .cshtml files:

  1. Open Tools menu.
  2. Choose Options…
  3. Go to Text Editor, and third choice; File Extension.
  4. Enter cshtml as Extension and choose HTML Editor in the dropdown.
  5. Click Add and OK. Now try to open a .cshtml file – you should get HTML colorization.

Remember to remove this setting when VS2010 officially gets Razor colorization and IntelliSense.

That’s it. Hopefully it will be a little bit easier on your eyes.

Read More »

How to Use the Omnibox API in Google Chrome

Posted on 26 July 2010 and tagged with 0 comments

The Omnibox API in Chrome is currently an experimental API, which means you can’t upload the extension to the gallery if your using it. Though, it works very well for local testing, and that is what we are going to do now.

When I first heard there was going to be an Omnibox API I figured it would let us hook in on every change in the address bar and then add my own results to it. However, this isn’t how the API was implemented, and after reading Aaron’s comment about why, I understand and believe it’s the right way to go.

[…] The omnibox has a very small results space. I'm hesitant to get into a
situation where a bunch of extensions are fighting to make their results the most relevant. […]

Aaron Boodman

In fact the only difference from how I thought it would work is that each extension sets a keyword (like search engines) in the manifest (omnibox_keyword) and this is the word the extension will respond to in the Omnibox. This means that, like Aaron said, we won’t have to fight with other extensions about space – we have our own reserved space in the results list. Smart!

How to Use

Like mentioned earlier, you need to first add a setting to the manifest.json file where you specify the keyword the Omnibox will respond to. This will look identical to how the custom search engines behave in the Omnibox

omnibox-1

Currently the Omnibox API consists of four events:

  • chrome.experimental.omnibox.onInputStarted
  • chrome.experimental.omnibox.onInputChanged
  • chrome.experimental.omnibox.onInputEntered
  • chrome.experimental.omnibox.onInputCancelled

The two events you will use the most are onInputChanged and onInputEntered. InputChanged occurs every time you type something in the Omnibar (after typing the keyword). This is also the event where you will be inserting the suggestions you want to show up in the results list. This is done in the following manner (placed in the background.html file):

chrome.experimental.omnibox.onInputChanged.addListener(function (text, suggest) {
    if (text.search('coffee') > -1) {
        var suggestions = [];

        suggestions.push({ content: 'Coffee - Wikipedia', description: 'Coffee - Wikipedia' });
        suggestions.push({ content: 'Starbucks Coffee', description: 'Starbucks Coffee' });

        suggest(suggestions);
    }
});

The suggest function we are calling at the end wants an array of suggestions. Each suggestion object has tree properties; content, description, and descriptionStyles (optional). The content property is the value the address bar will get when we choose this suggestion, and also the value we receive in the onInputEntered event. The description is the text we see in the results list. Lastly the descriptionStyles; it lets us style the description in different ways, e.g. green, grayed and bold. More on how this works later.

When running this code and typing our keyword in the Omnibox (e.g. “sp”), pressing space, and typing “coffee” you will get the following results:

omnibox-3

Pretty awesome, right! Now this example is quite useless but we could do something much smarter such as submitting this command to a web server, which then starts the coffeemaker and a notification popup is shown when it’s ready.

Whenever you press enter the value will be sent to the event listeners of the onInputEntered event. This event receives the entered text through it’s first parameter “text”. See example:

chrome.experimental.omnibox.onInputEntered.addListener(function (text) {
    alert('You entered: ' + text);
});

If you liked the idea about the coffeemaker, then here is where you will send the command to the web server. Or whatever you like it to do!

Beautify it

The suggestions objects we created earlier only used the content and description properties, and leaving out the descriptionStyles property. This property is quite cool (and nicely implemented). It determines how the description will look in the results list. We can choose between four different styles:

  • styleDim – slightly grayed out, used for helper text
  • styleMatch – used to display matched text, in bold
  • styleUrl – used for URLs and filenames
  • styleNone – resets the style to normal

They are then used by inserting in an array and specifying at which offset it should take effect. This means we can stack up as many different styles we want. We only have to set the offset at which their styles begin. Lets say we have a suggestion where we will display an URL and its page title. It would look like this in code:

var url = 'http://google.com';
var title = 'Google Search';

var suggestion = {
    content: url,
    description: url + ' - ' + title,

    descriptionStyles: [
        chrome.experimental.omnibox.styleUrl(0),
        chrome.experimental.omnibox.styleDim(url.length)
    ]
};

And this is how it looks in our Omnibar:

omnibox-4

Go create some code!

That’s all I have about the Omnibox API. It’s your turn now to create some nice extensions making use of this API, I sure will. However as noted before, you can’t upload extensions using experimental APIs to the extensions gallery. Hopefully it won’t take that long before the Chrome devs finish it.

If anything’s unclear, feel free to leave a comment :-)

Resources

Read More »

Loading Posts...