Monthly Archives: October 2011

Retrieving Contact Information In WP7.1 (Async/Sync Goodness)

Over the last few days I’ve come up with another application that I’d love to make, and a small part of it involves retrieving contact details. As part of the Mango update, one of the new APIs provided by Microsoft is the contacts API, falling under the Microsoft.Phone.UserData namespace.

This is awesome, except that because the contact search method is only provided asynchronously, I was having a massive headache trying to write code that would return a random contact, wrapped in a DataObject, synchronously. In effect, I wanted something like this:

[sourcecode language="c-sharp"]
public Person GetRandomPerson(string s)
{
Person myPerson = new Person();
Person contacts = new Contacts();
contacts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(contacts_SearchCompleted);
contacts.SearchAsync(String.Empty, FilterKind.None, "All Contacts");

return Person; //I’m not sure how this will ever work…
}

void contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
//convert a Contact object to Person object here
}
[/sourcecode]

After going around in circles with async and AsyncCallback and EAP and APM and a trillion google posts, it boiled down to a few things:

1) Passing the Person / DataObject through to the contact search callback as the third state/object parameter. – eg:

contacts.SearchAsync(String.Empty, FilterKind.None, myPerson);

2) using AutoResetEvent to control the thread execution, in order to prevent the GetRandomPerson() method from returning until we were sure the Contact Search had finished its thing – so creating an AutoResetEvent object, then calling are.WaitOne() after calling contacts.SearchAsync(), and in the callback, calling are.Set().

3) most importantly – calling all the code in a background thread. The UI thread doesn’t like being asked to .WaitOne() and just dies, so I used ThreadPool.QueueUserWorkItem(). Of course, this means that my code now goes Async -> Sync -> Async (which is still async.)

My final code looked like this:

[sourcecode language="c-sharp"]
private void Button_Click(object sender, RoutedEventArgs e)
{
//this should be done asynchronously – "request" a person

List<Person> people = new List<Person>();
PersonService ps = new PersonService();
ThreadPool.QueueUserWorkItem(func =>
{
for (int i = 0; i < 10; i++)
{
people.Add(ps.GetRandomPerson()); //you need to call this on a separate thread or it will lock the ui thread.
}
Dispatcher.BeginInvoke(() => { Status.Text = "done"; }); //your button click method is now also asynchronous
});
}

/*** Helper class ***/

public class PersonService
{
AutoResetEvent sync = new AutoResetEvent(false);

public Person GetRandomPerson()
{
Person person = new Person();
Contacts contacts = new Contacts();
contacts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(contacts_SearchCompleted);
contacts.SearchAsync(String.Empty, FilterKind.None, person);
sync.WaitOne();
return person;
}

void contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
Contact[] allContacts = e.Results.ToArray();
Contact randomContact = allContacts[new Random().Next(allContacts.Length)];
Person person = (Person)e.State;
person.Name = randomContact.DisplayName;

sync.Set();
}
}
[/sourcecode]

Note that the Windows Phone emulator comes loaded with some test contacts, but I’m not entirely sure they come with contact images so that’s something you may need to double check if you’re planning on using. If anyone’s got a better way of solving the same issue, let me know!

Using the DefaultButton property on asp:Panel controls with LinkButtons

When building a site, if you’ve got multiple input forms and buttons (such as a global search in a header and a contact us form as part of the page content), hitting the enter button on any part of the form normally defaults to submitting the very first form on the page (in the example, the search in the header). To get around this, all you need to do is set the DefaultButton property on a asp:Panel container to match the ID of the button you want to “submit” when pressing enter on a form within a panel.

This is all great, but unfortunately, it doesn’t work on all browsers if you’re setting the DefaultButton to a asp:LinkButton control – this is due to cross-browser differences in how they handle <a> tags. You could rewrite some of the javascript that enables the DefaultButton behaviour (following instructions on how to do so here), but an easier albeit hackier way is to just add an <asp:Button> with the same Command names and events as the LinkButton, hide it on the page with style=”display:none;” and then set the DefaultButton on the Panel to your hidden button. Easy!

Custom Web Fonts: IE8 and Different Font Weights

If you’ll remember a few posts back, I described how to import custom fonts for different weights. It turns out that this works for most browsers except IE8 (and probably 7, and 6, and so on). The original css to do the import was:

[sourcecode language="css"]

@font-face{
font-family: ‘MyFont’;
src: url(‘fonts/MyFontFile.eot’);
src: url(‘fonts/MyFontFile.eot?#iefix’) format(‘embedded-opentype’),
url(‘fonts/MyFontFile.woff’) format(‘woff’),
url(‘fonts/MyFontFile.svg#webfont’) format(‘svg’);
}

@font-face{
font-family: ‘MyFont’;
src: url(‘fonts/MyFontFileItalics.eot’);
src: url(‘fonts/MyFontFileItalics.eot?#iefix’) format(‘embedded-opentype’),
url(‘fonts/MyFontFileItalics.woff’) format(‘woff’),
url(‘fonts/MyFontFileItalics.svg#webfont’) format(‘svg’);
font-style: italic;
}

@font-face{
font-family: ‘MyFont’;
src: url(‘fonts/MyFontFileBold.eot’);
src: url(‘fonts/MyFontFileBold.eot?#iefix’) format(‘embedded-opentype’),
url(‘fonts/MyFontFileBold.woff’) format(‘woff’),
url(‘fonts/MyFontFileBold.svg#webfont’) format(‘svg’);
font-weight: bold;
}

[/sourcecode]

What IE8 doesn’t like, though, is overloading the font-family: it only seems to register the first font-face for a font-family name it’s given, and doesnt seem to like font-weight inside font-face either. So when you use the code above in IE8, instead of using the proper bold font-face, it does a “faux-bold”, which is sometimes acceptable, but normally horrendous. The only real way to fix this (and is what font-squirrel does) is to use separate font-family names and use font-family instead of font-weight in your IE-specific stylesheet:

[sourcecode language="css"]

@font-face{
font-family: ‘MyFont’;
src: url(‘fonts/MyFontFile.eot’);
src: url(‘fonts/MyFontFile.eot?#iefix’) format(‘embedded-opentype’),
url(‘fonts/MyFontFile.woff’) format(‘woff’),
url(‘fonts/MyFontFile.svg#webfont’) format(‘svg’);
}

@font-face{
font-family: ‘MyFontBold’;
src: url(‘fonts/MyFontFileBold.eot’);
src: url(‘fonts/MyFontFileBold.eot?#iefix’) format(‘embedded-opentype’),
url(‘fonts/MyFontFileBold.woff’) format(‘woff’),
url(‘fonts/MyFontFileBold.svg#webfont’) format(‘svg’);
}

h1{
font-family: MyFontBold;
}
[/sourcecode]

It’s hacky, I know, but it works – let me know if you’ve got other techniques to solve this issue :)

When Google Employees Flip

Well, okay, he didn’t flip – but this was never meant to be public. You can, ironically, find a really really interesting worthwhile read related to a lot of things about the IT/tech/web sector on Google+ here. I don’t know how long it’ll stay public though, so here’s my two favourite quotes:

“It’s not even super clear whose mom he was talking about, and doesn’t really matter, because nobody’s mom can use the goddamn website” – talking about the Amazon website

Google+ is a knee-jerk reaction, a study in short-term thinking, predicated on the incorrect notion that Facebook is successful because they built a great product. But that’s not why they are successful. Facebook is successful because they built an entire constellation of products by allowing other people to do the work. So Facebook is different for everyone. Some people spend all their time on Mafia Wars. Some spend all their time on Farmville. There are hundreds or maybe thousands of different high-quality time sinks available, so there’s something there for everyone.

Custom Search Refiners in SP2010 Gotcha

I thought I’d blogged about this previously, but it turns out I haven’t. So a colleague of mine ran into this issue where when you are setting the Filter Category Definition XML on the web part, after you save all the values reset, preventing you from customizing the refiners panel.

If this is happening to you, make sure you uncheck the “Use default configuration” setting, or it won’t persist your custom Filter Category Definition XML!

Custom Fonts For Your Website – Bold, Italics and IIS

While it’s still not really 100% universally supported, with a combination of .eot (IE), .svg (Safari/Chrome/Opera) and .woff (FF), you can get your website rendering a custom font for most people on most browsers. The css is pretty simple:

[sourcecode language="css"]

@font-face{
font-family: ‘MyFont’;
src: url(‘fonts/MyFontFile.eot’);
src: url(‘fonts/MyFontFile.eot?#iefix’) format(‘embedded-opentype’),
url(‘fonts/MyFontFile.woff’) format(‘woff’),
url(‘fonts/MyFontFile.svg#webfont’) format(‘svg’);
}

body { font-family: MyFont, Arial, Helvetica, sans-serif;}

[/sourcecode]

But wait, what if you’ve got three separate font files for different variants and weights, like bold and italics? No worries, you can just specify multiple font faces:

[sourcecode language="css"]

@font-face{
font-family: ‘MyFont’;
src: url(‘fonts/MyFontFile.eot’);
src: url(‘fonts/MyFontFile.eot?#iefix’) format(‘embedded-opentype’),
url(‘fonts/MyFontFile.woff’) format(‘woff’),
url(‘fonts/MyFontFile.svg#webfont’) format(‘svg’);
}

@font-face{
font-family: ‘MyFont’;
src: url(‘fonts/MyFontFileItalics.eot’);
src: url(‘fonts/MyFontFileItalics.eot?#iefix’) format(‘embedded-opentype’),
url(‘fonts/MyFontFileItalics.woff’) format(‘woff’),
url(‘fonts/MyFontFileItalics.svg#webfont’) format(‘svg’);
font-style: italic;
}

@font-face{
font-family: ‘MyFont’;
src: url(‘fonts/MyFontFileBold.eot’);
src: url(‘fonts/MyFontFileBold.eot?#iefix’) format(‘embedded-opentype’),
url(‘fonts/MyFontFileBold.woff’) format(‘woff’),
url(‘fonts/MyFontFileBold.svg#webfont’) format(‘svg’);
font-weight: bold;
}

[/sourcecode]

UPDATE: The css above won’t work for IE8 and below – you can find an explanation (and a workaround) here.

And lastly, if you’re hosting your website on IIS, you may need to add some MIME Types in order to get your custom fonts working on non-IE browsers, specifically:

  • .woff – application/x-woff
  • .svg – image/svg+xml

Thanks to these pages for all this great info!