Jan
18
2012

Add Google Plus One Extension to BlogEngine.NET

A few years ago I built my personal website using BlogEngine.NET, every once in a while I tend to pay attention to the site and “freshen it up”.  Back in December of 2011, I upgraded to version 2.5 of BlogEngine.NET and updated the theme.  Last night I added facebook like buttons to all those post and pages courtesy of isharpnote. Well I wanted to add a Google Plus One button to my site also but I could not find any BlogEngine.NET extensions for it, so what does every developer do, create one.  I started with the “Facebook Like with Google Plus Extension for BlogEngine 2.5” extension from isharpnote and tweaked it for my needs.

Creating the extension

To create a BlogEngine.NET extension you need a class and attribute it with the BlogEngine.Core.Web.Extensions.Extension attribute, like so:

[Extension(
	"Adds the Google Plus One to your blog Posts", 
	"1.0", 
	"<a href=\"http://www.josephguadagno.net/\">Joseph Guadagno</a>",
	800)]

Parameters explained

Parameters Explained
Parameter NameUsed for
Description A description of your extension
Version The version of your extension
Author A link to the author of the extension
Priority The priority of the extension, in relation to others.

This class will need to reside in the App_Code\Extensions folder of your site.

Next step, if you want to have settings, you will need to tell the extension manager that you have settings.  You do this by executing code similar to this, in the constructor of your extension or a method that is called in the constructor of your extension.

var settings = new ExtensionSettings(ExtensionName)
  {Help = "Adds Google Plus One to your Post Home page and Post page", IsScalar = true};

  settings.AddParameter("size", "Size", 20, false, false, ParameterType.ListBox);
  settings.AddValue("size", new[] { "standard", "small", "medium", "tall" }, "standard");
  ExtensionSettings = ExtensionManager.InitSettings(ExtensionName, settings);

In my extension I call a method called InitializeSettings in the constructor

public GooglePlusOne()
{
  InitializeSettings();
  Post.Serving += ServingHandler;
  Page.Serving += ServingHandler;
}

You'll notice that I attached two events, Post.Serving and Page.Serving, to the ServingHandler method. This will tell BlogEngine.NET that I want to know when it is serving up pages or blog posts.

Handling the page and post serving

void ServingHandler(object sender, ServingEventArgs e)
{
  if (!ExtensionManager.ExtensionEnabled(ExtensionName)) return;
  if (e.Location == ServingLocation.Feed) return;

  HttpContext context = HttpContext.Current;
  if (context != null)
  {
    System.Web.UI.Page page = context.CurrentHandler as System.Web.UI.Page;
    if (page != null)
    {
      ScriptInject(page);
    }
  }
  var post = sender as Post;
  if (post != null)
      e.Body += GetButton(post.AbsoluteLink.AbsoluteUri);
}

On line 3 you'll not the check to see if the extension is enabled.  Believe it or not, people might turn off your extension.

Line 4 checks to see if this is in a feed, if so, we do not want to apply the button to the page or post.

Line 6 - 10, I get a reference to the page so that I can inject the required JavaScript for the Google Plus One button.

public static void ScriptInject(System.Web.UI.Page page)
{
  HtmlGenericControl googleScript = new HtmlGenericControl("script");
  googleScript.Attributes["type"] = "text/javascript";
  googleScript.Attributes["src"] = "https://apis.google.com/js/plusone.js";
  page.Header.Controls.Add(googleScript);
}

Next, I get a reference to the post and append to the body of the post the Google Plus One button.

public static string GetButton(string url)
{
  string size = ExtensionSettings.GetSingleValue("size") jQuery152015469422082135964_1326909846817 "standard";
  string googlebutton = string.Format("<g:plusone size=\"{0}\" href=\"{1}\"></g:plusone>", size, url);
  return googlebutton;
}

That's it. You can download the complete extension here GooglePlusOne.cs (2.13 kb)

Jan
12
2012

DebuggerDisplay Attribute

Have you ever tried to debug an application and wish the Visual Studio debugger did not display {Namespace.ObjectName} when you wanted to see some of the details of the objects?

image

Visual Studio has an attribute that you can add to a class to inform the debugger what to display when it is displaying that class in the debugger.  As you probably guessed the attribute is called DebuggerDisplay.

How to Implement

Let’s say we have a simple class called Person, the Person class has 4 properties; FirstName, MiddleName, LastName and FullName. Here is the definition:

public class Person

{

  public string FirstName { get; set; }
  public string MiddleName { get; set; }
  public string LastName { get; set; }    
  public string FullName
  {
    get
    {
      return string.Format("{0} {1}{2}", FirstName,
        (string.IsNullOrEmpty(MiddleName)) ? string.Empty : MiddleName + "", 
        LastName);
    }
  }
}

 


Next, let’s assume we want to display the first and last name of the person when debugging.  We first need to add the DebuggerDisplay attribute to our class.  The DebuggerDisplay attribute can be found in the System.Diagnosis class of the .NET framework. The DebuggerDisplay works almost like the string.Format method, except you replace the numbers with the property / method names you want to display.

Example:

[DebuggerDisplay("FirstName={FirstName} LastName={LastName}")]

This will tell the debugger to display the string FirstName= with the value of the FirstName field in double quotes followed by LastName= with the value of the LastName field in double quotes every time it needs to display a person object.  Here is our new class:

[DebuggerDisplay("FirstName={FirstName} LastName={LastName}")]
public class Person
{
  public string FirstName { get; set; }
  public string MiddleName { get; set; }
  public string LastName { get; set; }    
  public string FullName
  {
    get
    {
      return string.Format("{0} {1}{2}", FirstName,
          (string.IsNullOrEmpty(MiddleName)) ? string.Empty : MiddleName + "", 
          LastName);
    }
  }
}

 

This will display like so:

image

You’ll notice this makes it easier to see what you are looking at.  It also works in the immediate window.

image

Summary

You can use more than just field names.  Method calls can be done (although probably not the best) and some calculations.  Take a look at the MSDN documentation for the DebuggerDisplay attribute for more information.

There is also an article titled DebuggerDisplay attribute best practices that you should read also.

Dec
31
2011

Using an ASP.NET DataRepeater ItemTemplate to create a jQuery Mobile Nested List with List Dividers

The jQuery Mobile framework has a list view widget that displays unordered lists in several different ways.  In the process of converting the Microsoft Global MVP Summit mobile site to use jQuery Mobile I wanted to change the way I displayed the events.  The idea was to have a header for each date that there was an event along with some of the details of the event.  Clicking on the event would take you the to event details page.

To accomplish this I used the count bubble, list dividers, content formatting and the search filter bar features of jQuery Mobile.

First let’s look at the HTML, for the sake of brevity I removed the ID fields from the HTML.

  1: <ul data-role="listview" data-inset="true" data-theme="d" data-filter="true">
  2:     <li data-role="list-divider">2/25/2012<span id="EventCount_0" class="ui-li-count">1</span></li>
  3:     <li>
  4:     <a href="/m/e.aspx?Id=45">
  5:         <h3><span>Northwest Harvest at MVP Summit 2012</span></h3>
  6:         <p><strong><span>Northwest Harvest Warehouse</span></strong></p>
  7:         <p class="ui-li-aside"><span>from 11:30 AM to 5:00 PM</span></p>
  8:     </a>
  9:     </li>
 10:     <li data-role="list-divider">2/27/2012<span class="ui-li-count">2</span></li>
 11:     <li>
 12:     <a href="/m/e.aspx?Id=48">
 13:         <h3><span>Consumer Camp: Bellevue</span></h3>
 14:         <p><strong><span id="VenueName_0">Microsoft Store: Bellevue</span></strong></p>
 15:         <p class="ui-li-aside"><span>from 5:00 PM to 8:00 PM</span></p>
 16:     </a>
 17:     </li>
 18:     <li>
 19:     <a href="/m/e.aspx?Id=46">
 20:         <h3><span>First Time MVPs Event</span></h3>
 21:         <p><strong><span>Rockbottom - Top of the Rock</span></strong></p>
 22:         <p class="ui-li-aside"><spa>from 6:00 PM to 9:00 PM</span></p>
 23:     </a>
 24:     </li>
 25: </ul>

From this HTML markup the jQuery Mobile framework will generate a view that looks like this:

image

The jQuery Mobile ListView

Creating the ListView

The start of the unordered list, Line 1, has 4 attributes:

  1: <ul data-role="listview" 
  2: data-inset="true" 
  3: data-theme="d" 
  4: data-filter="true">

The data-role of listview tells the jQuery Mobile framework to use the jQuery Mobile Listview widget. Setting the data-inset attribute to true tells the jQuery Mobile framework to indent the list view and add the rounded edges. The data-theme attribute tells jQuery Mobile to use the d theme. Setting the data-filter equal to true tells the jQuery Mobile framework to add the filter items text box up top. No additional work is needed to add the filter, it will search all of the ListItems that are part of this unordered list who’s data-role attribute is not set to list-divider for the text entered.

The List Divider

Adding the data-role of list-divider (Line 2 of the initial example) will make that list item appear as a divider.  You can use this attribute to group items, in my case, I grouped by date.

To establish the count bubble you will need to wrap the count of item around a span tag and give it the class of ui-li-count, as shown in Line 2.

Here’s an annotated image with markup.

image

The item in red is the individual list item which will be discussed in the next section.

The Items

Each sub item under the list divider needs to be it’s own Anchor element ( A )  wrapped in a ListItem (LI) tag as shown in lines 3-9 and 11-24 above.

  1: <li>
  2:     <a href="/m/e.aspx?Id=45">
  3:         <h3><span>Northwest Harvest at MVP Summit 2012</span></h3>
  4:         <p><strong><span>Northwest Harvest Warehouse</span></strong></p>
  5:         <p class="ui-li-aside"><span>from 11:30 AM to 5:00 PM</span></p>
  6:     </a>
  7: </li>

Each LI formatted above will generate a “row” as highlighted in the red boxed image above within your browser.  Clicking on one of those links will take you to the page specified in Anchor tag. In order to get the times to “float” to the left, you will need to use the ui-li-aside class.  Note, the > image will get added automatically by the framework.

Creating the jQuery ListView with an ASP.NET DataRepeater Control

In order to accomplish this, I went with a DataRepeater within a DataRepeater .  The first, or outside, DataRepeater (DateRepeater)will get a list of distinct dates from the data store in order to create the List Dividers. The second, or inner, DataRepeater (EventRepeater) will list all of the events for the day specified by the DateRepeater.

Let’s take a look at the code:

  1: <asp:Repeater runat="server" ID="DateRepeater" DataSourceID="EventDatesDataSource" OnItemDataBound="DateRepeaterOnItemDataBound">
  2:     <HeaderTemplate>
  3:         <ul data-role="listview" data-inset="true" data-theme="d" data-filter="true">
  4:     </HeaderTemplate>
  5:     <ItemTemplate>
  6:         <li data-role="list-divider"><%# Container.DataItem %>
  7:             <asp:Label runat="server" ID="EventCount" class="ui-li-count"></asp:Label>
  8:         </li>
  9:         <asp:Repeater runat="server" ID="EventRepeater" OnItemDataBound="EventRepeaterOnItemDataBound">
 10:             <ItemTemplate>
 11:                 <li>
 12:                 <asp:HyperLink runat="server" ID="EventUrl">
 13:                     <h3><asp:Label runat="server" ID="EventName" /></h3>
 14:                     <p><strong><asp:Label runat="server" ID="VenueName"></asp:Label></strong></p>
 15:                     <p class="ui-li-aside"><asp:Label runat="server" ID="EventDate"></asp:Label></p>
 16:                 </asp:HyperLink>
 17:                 </li>
 18:             </ItemTemplate>
 19:         </asp:Repeater>
 20:     </ItemTemplate>
 21:     <FooterTemplate>
 22:         </ul>
 23:     </FooterTemplate>
 24: </asp:Repeater>

In lines 2-4, using the HeaderTemplate property of the DateRepeater DataRepeater control I create the initial ListView. It is then closed in the lines 21-24 using the FooterTemplate of the DateRepeater DataRepeater control. Next in the ItemTemplate property (Line 6-8) of the DateRepeater DataRepeater control, I create a list divider by adding a ListItem (LI) with the data-role of list-divider with a label for the date.  Line 7 has a label control with a class of ul-li-count that holds the count of events that date.

Now within the ItemTemplate property of the DateRepeater DataRepeater control I also have another DataRepeater, EventRepeater. This DataRepeater will iterate through all the events for a day and create the individual ListItems (LI) for each event on that day (Lines 11-17). Notice how the ListItem is wrapped in an ASP:HyperLink control.  This will provide the hyperlink to the event details page.

That sums up creating jQuery Mobile listview using an ASP.NET DataRepeater control.

Dec
31
2011

Converting an ASP.NET “Mobile” site to use jQuery Mobile

Building upon my previous post Introduction to jQuery Mobile, I wanted to share how I converted the Microsoft Global MVP Summit mobile site to use jQuery Mobile.

Getting Started

The first step was to look at the existing ASP.NET Master Page that the site was using and see where I had to make changes.  I included the skeleton mobile master page, prior to jQuery Mobile below.  Please note, I removed parts of the page that do not relate to the blog post.

  1: <%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Mobile.master.cs" Inherits="MVPSummitEvents.Website.Mobile" %>
  2: 
  3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  4: <html xmlns="http://www.w3.org/1999/xhtml" >
  5: <head runat="server">
  6:     <title>MVP Summit Events - Mobile - </title>
  7:     <asp:ContentPlaceHolder ID="head" runat="server">
  8:     </asp:ContentPlaceHolder>
  9: </head>
 10: <body>
 11:     <form id="form1" runat="server">
 12:     <div id="mHead"><h1>MVP Summit Events</h1></div>
 13:     <div id="mMenu">
 14:         <asp:HyperLink runat="server" ID="hlMain" NavigateUrl="~/m/default.aspx" Text="Home" ToolTip="Home" /> | 
 15:         <asp:HyperLink runat="server" ID="hlMap" NavigateUrl="~/m/map.aspx" Text="Map" ToolTip="Map" /> | 
 16:         <a href="http://tinyurl.com/4e5mp5p" title="Windows Phone 7 App">Window Phone 7</a> App. |
 17:         <a href="http://itunes.apple.com/us/app/mvp-events/id416291827?mt=8">iPhone</a> App.
 18:     </div>
 19:     <div id="mBody">
 20:         <asp:ContentPlaceHolder ID="CphBody" runat="server">
 21:         
 22:         </asp:ContentPlaceHolder>
 23:     </div>
 24:     </form>
 25:     <div id="mFoot">Copyright ©2009-2012, <a href="http://www.josephguadagno.net" title="Joseph Guadagno">Joseph Guadagno</a> | <a href="http://twitter.com/jguadagno" title="Follow jguadagno">@jguadagno</a> | <a href="mailto:jguadagno@sevdnug.org">Contact</a></div>
 26: </body>
 27: </html>

Converting the document head

The first thing I needed to do was to update the DOCTYPE on line 3 to

  1: <!DOCTYPE HTML>

Next was to include the jQuery Mobile scripts and css files, after that my head section looked like this:

  1: <%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Mobile.master.cs" Inherits="MVPSummitEvents.Website.Mobile" %><!DOCTYPE html> 
  2: <!DOCTYPE html> 
  3: <html xmlns="http://www.w3.org/1999/xhtml" >
  4: <head runat="server">
  5: 	<title>MVP Summit Events - Mobile - </title>
  6: 	<meta name="viewport" content="width=device-width, initial-scale=1"> 
  7: 	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" />
  8: 	<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
  9: 	<script type="text/javascript" src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js"></script>
 10: 	<asp:ContentPlaceHolder ID="HeadContent" runat="server" />
 11: 	<link id="Link1" rel="stylesheet" runat="server" href="/css/m.css" />
 12: 	<script type="text/javascript" src="../js/analytics.js"></script>
 13: 	<script type="text/javascript" src="../js/analytics.jqmobile.js"></script>
 14: </head>

Again, I removed parts that are not required for this post.

You should notice that line 2 is now different and I added lines 6, 7,8,9 and 13.  Line 6 contains the viewport meta tag, the description from the jQuery Mobile docs is …

Note above that there is a meta viewport tag in the head to specify how the browser should display the page zoom level and dimensions. If this isn't set, many mobile browsers will use a "virtual" page width around 900 pixels to make it work well with existing desktop sites but the screens may look zoomed out and too wide. By setting the viewport attributes to content="width=device-width, initial-scale=1", the width will be set to the pixel width of the device screen.

Lines 7, 8, 9 contain the references to jQuery Mobile style sheet, the jQuery library and the jQuery Mobile library. Line 13, is a work around for using Google Analytics which is described here.

Converting the Document Body

Looking at the body of the Master Page, I was almost ready for the jQuery Mobile conversion.

  1: <div id="mHead"><h1>MVP Summit Events</h1></div>
  2:     <div id="mMenu">
  3:         <asp:HyperLink runat="server" ID="hlMain" NavigateUrl="~/m/default.aspx" Text="Home" ToolTip="Home" /> | 
  4:         <asp:HyperLink runat="server" ID="hlMap" NavigateUrl="~/m/map.aspx" Text="Map" ToolTip="Map" /> | 
  5:         <a href="http://tinyurl.com/4e5mp5p" title="Windows Phone 7 App">Window Phone 7</a> App. |
  6:         <a href="http://itunes.apple.com/us/app/mvp-events/id416291827?mt=8">iPhone</a> App.
  7: </div>
  8: <div id="mBody">
  9:     <asp:ContentPlaceHolder ID="CphBody" runat="server">
 10:     </asp:ContentPlaceHolder>
 11: </div>
 12: <div id="mFoot">Copyright ©2009-2012, <a href="http://www.josephguadagno.net" title="Joseph Guadagno">Joseph Guadagno</a> | <a href="http://twitter.com/jguadagno" title="Follow jguadagno">@jguadagno</a> | <a href="mailto:jguadagno@sevdnug.org">Contact</a></div>
 13: </form>

I have my Master Page broken up into a header, menu, body, and footer. All I had to do was assign the jQuery Mobile data-role attributes and I was done.  However I took this time to “tweak” the layout of the mobile site look more like it would on the iPhone and other mobile devices.  I still keep the header, but moved the menu to the footer section and moved the existing footer to an about page.  The new body of the mobile Master Page looks like this.

  1: <div data-role="page">    
  2:   <div data-role="header" data-theme="b"><h1><asp:Label runat="server" ID="HeaderLabel"></asp:Label></h1></div>
  3:   <div data-role="content" data-theme="b">
  4:     <asp:ContentPlaceHolder ID="BodyContent" runat="server">
  5:     </asp:ContentPlaceHolder>  
  6:   </div>
  7:   <div data-role="footer" data-theme="b">
  8:     <div data-role="navbar">
  9:       <ul>
 10:         <li><asp:HyperLink runat="server" NavigateUrl="~/m/default.aspx" data-icon="home">Home</asp:HyperLink></li>
 11:         <li><asp:HyperLink runat="server" NavigateUrl="~/m/map.aspx" data-ajax="false">Map</asp:HyperLink></li>
 12:         <li><asp:HyperLink runat="server" NavigateUrl="~/m/Apps.aspx">Apps</asp:HyperLink></li>
 13:         <li><asp:HyperLink runat="server" NavigateUrl="~/m/About.aspx" data-icon="info">About</asp:HyperLink></li>
 14:       </ul>
 15:     </div>
 16:   </div>
 17: </div>

To me this seems quite readable and clearly identifies what each section (div) is responsible for.

Let’s break it down.

First all the previous DIV’s in between the FORM tags where placed within a

  1: <div data-role="page"></div>

tag. The next step was to convert each of the DIV’s that I had into a jQuery Mobile DIV. There is really no ‘jQuery Mobile DIV’ just an attribute that tells jQuery what “section” of the document this div is for.  I added the data-role=”header” to the DIV with the ID of mHead, I added the data-role=”content” to the DIV with the ID of mBody and I added the data-role=”footer” to the DIV with the ID of mFooter.

“Ok but what happened to the mMenu DIV” you ask.  Take a look at line 8 in the code sample above.  I moved the “menu” to the footer of the new document and assigned it a data-role of navbar. This is a jQuery Mobile widget that creates a simple menu of buttons out of all of the listitem elements of the unordered list. The data-icon attribute is an attribute that allows you to indicate one of the 18 built in icons for any jQuery Mobile button.

After this, I was done.  I now have a jQuery Mobile version of the Microsoft Global MVP Summit site that looks the same on virtually every mobile browser with little to no work.

Up next, how to convert other elements of an ASP.NET mobile site to use jQuery Mobile widgets.

Dec
31
2011

Introduction to jQuery Mobile

Back in November I sat in on a session by Scott Hanselman on creating a mobile site on ASP.NET using jQuery Mobile.  While I was watching this session I could not stop thinking how easy is this, I can do this for the mobile version of the Microsoft Global MVP Summit mobile site. So like most of us, it took me a month to get to it.

A few days ago while on vacation and every one was asleep, I started to play around with jQuery mobile and in about an hour I had a sample site created.  Here’s how you can get started.

Getting started with jQuery Mobile

According the jQuery Mobile website, jQuery Mobile is…

A unified, HTML5-based user interface system for all popular mobile device platforms, built on the rock-solid jQuery and jQuery UI foundation. Its lightweight code is built with progressive enhancement, and has a flexible, easily themeable design

To get started with jQuery Mobile you can head over to their Quick Start Guide.  Here is the minimum HTML document that you need for jQuery Mobile.

  1: <!DOCTYPE html> 
  2: <html> 
  3: 	<head> 
  4: 	<title>My Page</title> 
  5: 	<meta name="viewport" content="width=device-width, initial-scale=1"> 
  6: 	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" />
  7: 	<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
  8: 	<script type="text/javascript" src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js"></script>
  9: </head> 
 10: <body> 
 11: <div data-role="page">
 12: 	<div data-role="header">
 13: 		<h1>My Title</h1>
 14: 	</div><!-- /header -->
 15: 	<div data-role="content">	
 16: 		<p>Hello world</p>		
 17: 	</div><!-- /content -->
 18: </div><!-- /page -->
 19: </body>
 20: </html>

The first this you will notice is the simple DOCTYPE.

<!DOCTYPE html>

Next you will need to include a reference to the jQuery Mobile scripts and css files in the HEAD section of the document.

  1: <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" />
  2: <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
  3: <script type="text/javascript" src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js"></script>

And then finally in your HTML Body, you need to create a “page”. You do this by creating a DIV and an assigning the role of page to it.

  1: <div id="#default" data-role="page">
  2: ...
  3: </div>

The id is optional and can be used to have more than one page within a document.  For more on the page structure, check out the Anatomy of a Page in the jQuery Mobile docs.

That’s all you need for the bare minimal jQuery Mobile page.

jQuery Mobile Page Parts

jQuery Mobile pages are made up of potentially 3 parts; the header, the content (body) and the footer.  These parts are outlined by creating a div and assigning a role to it.  The roles are data-role=”header”, data-role=”content”, and data-role=”footer”.

  1: <div data-role="page"> 
  2: 	<div data-role="header">...</div> 
  3: 	<div data-role="content">...</div> 
  4: 	<div data-role="footer">...</div> 
  5: </div> 

Header Part

Is defined by following markup.

  1: <div data-role="header">...</div>  

The header part of the document is where you place content that you want as the head or beginning part of the page. This is typically page titles and toolbars.

Content Part

Is defined by following markup.

  1: <div data-role="content">...</div>  

The content part of the document is where you place the page content.

Footer Part

Is defined by following markup.

  1: <div data-role="footer">...</div>  

The footer part of the document is where you place the footer content. This is typically navigation, copyright information, etc.

Hopefully, I armed you with enough information to get started with jQuery Mobile.  In the next few posts I will talk about how I converted the Microsoft Global MVP Summit mobile site to use jQuery Mobile.

Feb
4
2010

Using Bing Maps Web Services Imagery Service

In my previous post, Using the Bing Maps Web Services for Geocoding Addresses, I talk about geocoding addresses using the Bing Maps Web Services. Now it is time to talk about getting imagery of maps, roads or aerials views for addresses or geocodes.

In order to get started using the Bing Maps Web Services, check out the previous post Getting Started section.

Bing Maps Web Services

Bing Maps Web Services is a set of Web services that allow you to add mapping and search functionality to your application, including location finding, map imagery, and routing capabilities. For example, you can:

Use the Imagery Service to:

  • Return a link to a map with a pushpin at a specific location
  • Provide a road map or bird’s eye or aerial imagery to you application

Use the Route Service to:

  • Get directions that include traffic warnings and route hints between multiple locations.
  • Get directions from all major roads to a destination (1-click directions, also referred to as a "party map") and then use the Imagery Service to map those routes.

For this post we will cover the Imagery service.

Just like the Geocode Service, there is a request, MapUriRequest, and response, MapUriResponse, object for the Imagery Service.

In order to get the Uri to display a map in your application you will need to use the imagery service client, ImageryServiceClient. The ImageryServiceClient needs to be instantiated with the WCF endpoint to use, by default it should be ‘BasicHttpBinding_IImageryService’. Then call the GetMapUri method passing your MapUriRequest object.

ImageryServiceClient imageryService = new ImageryServiceClient("BasicHttpBinding_IImageryService");
MapUriResponse mapUriResponse = imageryService.GetMapUri(mapUriRequest);
Building the MapUriRequest

The MapUrilRequest has two properties that need to be populated; the Credentials property which should contain you Bing Maps Id and either the Center, MajorRoutesDestination, or Pushpins property.  The code snippet below demonstrates instantiating the MapUriRequest and setting the properties based on values passed into a method (outlined later).

MapUriRequest mapUriRequest = new MapUriRequest
    {
      Credentials = new Credentials {ApplicationId = appId},
      Pushpins = pushpins,
      Center = new Location {Latitude = latitude, Longitude = longitude}
    };

Now you can customize the options for the map using the MapUriOptions property of the MapUriRequest object. Here is a list of the properties from the MSDN documentation:

Property name Description

DisplayLayers

A string array indicating the layer data to display on the map. Optional. The default value is null.

ImageSize A SizeOfint Class object specifying the height and width of the image to return. Optional. The default width is 350 and the default height is 350.
ImageType An ImageType Enumeration value specifying the format of the image to return. Optional. The default value is ImageType.Default, which means the default changes depending on the map style specified.
PreventIconCollision A bool indicating whether or not to separate pushpin icons that are close to each other on the map so that they are more visible. Optional. The default value is false.
Style A MapStyle Enumeration value specifying the map style of the image to return. Optional. The default value is MapStyle.Road.
UriScheme A UriScheme Enumeration value specifying the URI scheme to return. Optional. The default value is UriScheme.Http.
ZoomLevel An int indicating the zoom level of the map to return. Optional.

Assigning some of the options:

// Set the map options
MapUriOptions mapUriOptions = new MapUriOptions();
mapUriOptions.Style = MapStyle.Road;
mapUriOptions.ZoomLevel = zoom;
mapUriOptions.ImageSize = new SizeOfint {Height = height, Width = width};
// Set the options property of the request.
mapUriRequest.Options = mapUriOptions;

Now you are ready to call the image service client to get the MapUriResponse.

ImageryServiceClient imageryService = new ImageryServiceClient("BasicHttpBinding_IImageryService");
MapUriResponse mapUriResponse = imageryService.GetMapUri(mapUriRequest);

Here is a helper class,

,  which wraps the GetMapUri function with 8 different overloads.

Working with the MapUriResponse

The MapUriResponse object has three properties:

Name Description
BrandLogoUri The System.Uri of the Bing Maps brand logo image.
ResponseSummary A ResponseSummary Class object describing the response that was returned by the service.
Uri A string that is the URI of the requested map.

For brevity sake, we will just use the Uri property.  You should, though, for good programming practices, check the ResponseSummary property for any exceptions.

string mapUri = Imagery.GetMapUri("YourAppId", 47.62, -122.2);
imgMap.imageUrl = mapUri;

This call retrieve the Uri to use to display a 200x200 road map of the area at latitude 47.62 and longitude -122.2 with a zoom of 14, which is downtown Bellevue, WA.

image

If you want to add pushpins or markers similar to the above image you will need to populate the an array of PushPin objects. A PushPin object has an IconStyle which is the type of icon to use, a Label which an optional text to display on the pushpin (only works with certain pushpins) and the Location which contains the latitude and longitude that the pushpin should be located at.

That’s it.  It seems like a lot of work for a one line call.  With the attached Imagery.cs class, a lot of the overhead work was done for you.

Feb
4
2010

Using the Bing Maps Web Services for Geocoding Addresses

For the MVPSummitEvents and Mix10Events site I wanted to create a map of all of the events listed on the site. In order to do that I needed to Geocode all of the addresses for the events.  There are several services out there for geocoding an address, Microsoft, Yahoo, and Google provide this service as well as others.  I decided to go with the Microsoft Bing services, being a Microsoft MVP.

Getting Started

Let’s get started. MSDN has just about everything you need to get started with using the Bing Map Web Services. 

Step 1: The first step is to get a key or token to use in your application for the Bing Maps Web Services application. This can be done by visiting the Bing Maps Account center and clicking on Create a Bing Maps account.

Step 2: If you are using Visual Studio, add a service reference to one or more Bing Maps Web Services that provide the features you need. See the Generating Client Proxy Classes topic and the Bing Maps Web Services Metadata topic.

VirtualEarthWebServicesWhether you used Visual Studio or the svcutil application you should have one file, most likely named VirtualEarthWebServices.cs. The file will contain a bunch of wrapper classes around the Bing Maps Web Services, and the required Windows Communication Foundation (WCF) classes. You will also see the generated configuration settings for the app or web config files.

Step 3: Set every Bing Maps Web Services request a valid Credentials property. You will see more on this in a bit.

Geocoding an Address

There are two properties that are required to successfully request a GeoCode for an address.

  1. 1) Set the Credential Property of the GeoCodeRequest object
  2. 2) Set either the Query property or Address property of the GeoCodeRequest object.

Here is a helper function that wraps the call to GeoCodeRequest.

/// <summary>
/// Gets the location.
/// </summary>
/// <param name="appId">The app id.</param>
/// <param name="address">The address.</param>
/// <returns></returns>
public static GeocodeResponse GetGeocodeResponse(string appId, string address)
{
    GeocodeRequest geocodeRequest = new GeocodeRequest
      {
          Credentials = new Credentials {ApplicationId = appId},
          Query = address
      };
    ConfidenceFilter[] filters = new ConfidenceFilter[1];
    filters[0] = new ConfidenceFilter {MinimumConfidence = Confidence.High};
    GeocodeOptions geocodeOptions = new GeocodeOptions {Filters = filters};
    geocodeRequest.Options = geocodeOptions;

    GeocodeServiceClient geocodeServiceClient = new GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
    return geocodeServiceClient.Geocode(geocodeRequest);
}

This method will return a GeocodeResponse object. The GeocodeResponse object contains three properties that are populated based on the query.

Name Description

BrandLogoUri

The System.Uri of the Bing Maps brand logo image. (Inherited from the ResponseBase Class.)

ResponseSummary A ResponseSummary Class object describing the response that was returned by the service. (Inherited from the ResponseBase Class.) This class returns any exceptions that we raised during the request.
Results A GeocodeResult Class array, where each element is a possible match returned by the Geocode Service.

To keep this article short(er) I will just cover the Results object. Depending on the Confidence filter and Geocode options that were set in the call you could receive more than one result.

Let’s assume that we only want to work with the first result and get the Geocode for “1 Microsoft Way, Redmond, WA”. We simply call the static method of GetGeocodeResponse and pass in the Bing Maps API key and the address to search for.

var address = "1 Microsoft Way, Redmond, WA";
GeocodeResponse response = GetGeocodeResponse(appId, address);

Assuming the address was found we can now work with the properties of the GeocodeResult class to find out the Geocode.  The Geocode is located in the Locations property which is an array of GeocodeLocation objects. If the Count of the Locations is greater than one, let’s just take the first one and update the txtLatitude and txtLongitude objects.

if (response.Results != null)
{
	var geocodeLocation = response.Results[0].Locations[0];
	if (geocodeLocation != null)
	{
	    txtLatitude.Value = geocodeLocation.Latitude;
	    txtLongitude.Value = geocodeLocation.Longitude;
	}
	else
	{
	    txtLatitude.Value = txtLongitude.Value = 0;
	}
}

That’s it. Next up, using the Bing Maps Web Services for getting map images.

Jan
28
2010

Mix 10 Events Site Launched

Are you going to Mix10 in March? If so, you might want to check out the new site I launched call Mix 10 Events.  Mix 10 Events will be you one stop shop for all of the events and after parties at Mix10.

Anyone can create an event on the sign. All you need to do is sign in with you Windows Live credentials, and link to create an event will appear.  Please note, the event will not be available until it is reviewed and approved for display.

VisitMixEvents.info

Staying connected

Don’t feel like checking out the site every day to see what is happening? Here are a few resources to help you.

The site http://www.visitmixevents.info/default.aspx
RSS Feed http://www.visitmixevents.info/rss.ashx
GeoRSS Feed http://www.visitmixevents.info/rss.ashx?format=geo
iCal Feed http://www.visitmixevents.info/calendar.ashx
Map of events http://www.visitmixevents.info/map.aspx

Mobile Users

You will be able to view all of the events that are happening, even filter by day. In addition, you can view the events on a Map, and check out the event info.

Mobile Site http://www.visitmixevents.info/m/default.aspx
Mobile Map http://www.visitmixevents.info/m/m.aspx

Las Vegas

In case you do not want to check out the events, I mean “It’s Vegas Baby”. Here are some other resources, also accessible from the site.

Bing Local http://www.bing.com/local/default.aspx?q=Las+Vegas%2C+Nevada
Official Las Vegas Tourism http://www.visitlasvegas.com/vegas/index.jsp
Vegas.com Guide http://www.vegas.com/traveltips/
Dec
23
2009

MVP Summit Events Launched

One thing that I have noticed of the past few years when it comes to conference or “Summits” is that there are a lot of after parties, tweets, etc. that happen.  Most of the time it is difficult to get the word out about these events or even find out about them.  That’s where MVPSummitEvents.com comes in.  The site will hopefully be a one stop shop to find public events that are happening at the Microsoft 2010 MVP Global Summit.

From the site you can add events, create venues, display events, subscribe to the RSS feed or iCal feed, download an event to outlook or calendar client that can consume a .VCS file. Note: the creation of events and venues requires you to sign in using your Windows Live Id account, no information from Live is used within our site.

If the site is successful, I plan to white label it to use with other events like MIX2010, TechEd, PDC, etc.

Let me know what you think at jguadagno@sevdnug.org

Nov
9
2009

A November to Remember

And no it is not because the Yankees won the World Series (although congrats to them) it is because it has been an awesome month for me personally and professionally.

On the personal front…

My son’s baseball team, which I am an assistant coach, finished the season undefeated in regular season games (end of year tournament in next week).  My son hit his first over the fence homerun which was a Grand Slam (technically not November but pretty awesome). My daughter's softball team, which I am an assistant coach, finished the season undefeated in regular season games (end of year tournament in next week).

I get to go to fly back to NY in a few days to see family and friends and wish my mother a happy 60th birthday.

On the professional front…

I was elected to the North American INETA board of directors.

I was elected to the AZGiveCamp executive committee, VP of Operations.  As the VP I will oversee the activities of the Logistics, Sponsorship, Technology and Publicity teams.

I put together my first Code Camp, Desert Code Camp.

I am presenting a Bird of Feather session at PDC with Chris Woodruff on “How to Build and Enrich Your Technical and Local Community” on Tuesday Nov 17 from 11a – 12p.  Stop by if you want to see how to build your community.

 

That’s it for now.  Hopefully I can relax a bit in December.



About the author

Joseph Guadagno Name: Joseph Guadagno
Occupation: Programmer, President of INETA North America, President of SEVDNUG, Microsoft Visual C# MVP
Location: Chandler, AZ

Joseph Guadagno RSS Joseph Guadagno Twitter Joseph Guadagno Linked In

Month List