Musings on Agile Development and Visual Studio ALM Tools

PAGES

26

Mar 10

Including Overestimates in MSF Agile Burndown Report



After using the MSF Agile Burndown report for a few weeks in our new TFS 2010 environment, I have to say I am a huge fan.  I especially find the assignment of Work (hours) portion to be very useful in motivating the team to keep their tasks up to date every day.  Here is a view of the report that you get out of the box.

image

However, I have one problem.  I”d like the top line to have some more meaning.  Specifically, when it is changing is that an indication of scope creep, mis-estimation or a combination of the two.  So, today I decided to try to build in a view that would show overestimated time.  This would give me a more consistent top line.  My idea was to add another visual area on top of the graph whenever my originally estimated time was greater than the sum of completed and remaining.  This will effectively show me at least when the top line goes down whether it was scope change or over-estimation.

Here is the final result.

image

How did I do it? 

Step 1: Add Cumulative_Original_Estimate field to the dsBurndown

My approach was to follow the pattern where the completed time is included in the burndown chart and add my Overestimated hours.  First I added a field to the dsBurndown to hold the estimated time.

        <Field Name=”Cumulative_Original_Estimate”>
         
<DataField></DataField>
         
<rd:TypeName>System.Int32</rd:TypeName>
       
</Field>

Step 2: Add a column to the query

SELECT
{
   
[Measures].[DateValue],
   
[Measures].[Work Item Count],
   
[Measures].[Microsoft_VSTS_Scheduling_RemainingWork],
   
[Measures].[Microsoft_VSTS_Scheduling_CompletedWork],
   
[Measures].[Microsoft_VSTS_Scheduling_OriginalEstimate],
   
[Measures].[RemainingWorkLine],
   
[Measures].[CountLine]

Step 3: Add a new Item to the QueryDefinition

<Item>
<ID xsi:type=”Measure”>
<MeasureName>Microsoft_VSTS_Scheduling_OriginalEstimate</MeasureName>
<UniqueName>[Measures].[Microsoft_VSTS_Scheduling_OriginalEstimate]</UniqueName>
</ID>
<ItemCaption>Cumulative Original Estimate</ItemCaption>
<FormattedValue>true</FormattedValue>
</Item>

Step 4: Add a new ChartMember to DundasChartControl1

The burndown chart is called DundasChartControl1.  I need to add a ChartMember for the estimated time.

<ChartMember>
 
<Label>Cumulative Original Estimate</Label>
</ChartMember>

Step 5: Add a ChartSeries to show the Overestimated Time

<ChartSeries Name=”OriginalEstimate”>
 
<Hidden>=IIF(Parameters!YAxis.Value=”count”,True,False)</Hidden>
 
<ChartDataPoints>
   
<ChartDataPoint>
     
<ChartDataPointValues>
       
<Y>=IIF(Parameters!YAxis.Value = “hours”, IIF(SUM(Fields!Cumulative_Original_Estimate.Value)>SUM(Fields!Cumulative_Completed_Work.Value+Fields!Cumulative_Remaining_Work.Value), SUM(Fields!Cumulative_Original_Estimate.Value-(Fields!Cumulative_Completed_Work.Value+Fields!Cumulative_Remaining_Work.Value)),Nothing),Nothing)</Y>
     
</ChartDataPointValues>
     
<ChartDataLabel>
       
<Style>
          <FontFamily
>Microsoft Sans Serif</FontFamily>
          <FontSize
>8pt</FontSize>
        </
Style>
     
</ChartDataLabel>
     
<Style>
        <Border
>
          <Color
>#9bdb00</Color>
          <Width
>0.75pt</Width>
        <
/Border>
        <Color
>#666666</Color>
        <BackgroundGradientEndColor
>#666666</BackgroundGradientEndColor>
      </
Style>
     
<ChartMarker>
       
<Style />
      </
ChartMarker>
     
<CustomProperties>
       
<CustomProperty>
         
<Name>LabelStyle</Name>
         
<Value>Top</Value>
       
</CustomProperty>
     
</CustomProperties>
   
</ChartDataPoint>
 
</ChartDataPoints>
 
<Type>Area</Type>
 
<Subtype>Stacked</Subtype>
 
<Style />
  <
ChartEmptyPoints>
   
<Style>
      <Color
>#00ffffff</Color>
    </
Style>
   
<ChartMarker>
     
<Style />
    </
ChartMarker>
   
<ChartDataLabel>
     
<Style />
    </
ChartDataLabel>
 
</ChartEmptyPoints>
 
<LegendName>Default</LegendName>
 
<ChartItemInLegend>
   
<LegendText>Overestimated Hours</LegendText>
 
</ChartItemInLegend>
 
<ChartAreaName>Default</ChartAreaName>
 
<ValueAxisName>Primary</ValueAxisName>
 
<CategoryAxisName>Primary</CategoryAxisName>
 
<ChartSmartLabel>
   
<Disabled>true</Disabled>
   
<MaxMovingDistance>22.5pt</MaxMovingDistance>
 
</ChartSmartLabel>
</ChartSeries>

That”s it.  I find the improved report to add some value over the out of the box version.  You can download the updated rdl for the report here

23 comments , permalink


12

Mar 10

tfs 2010 RC Agile Process template update – New Task progress report



Maybe my next post will just be about why I am so excited and impressed with the out of the box templates.  But, for this first blog with my new focus, I thought I would just walk through the process I went through to create a task progress report (to enhance the out of the box Agile template).

So, I started with the MSF for Agile Development 5.0 RC template.  After reviewing the template, I came away pretty excited about many of the new reports.  I am especially excited about the reporting services reports.  The big advantage I see here is that these are querying the Warehouse directly instead of the Analysis Services Cube which means that they are much closer to real-time which I find very important for reports like Burndown and task status.  One report that I focused on right away was the User Story Progress Report.  An overview is shown below:

Example Stories Progress Report

This report is very useful, but a lot of our internal managers really prefer to manage at the task level and either don”t have stories in TFS or would like to view this type of report for tasks in addition to the User Stories.  So, what did I do?

Step 1: Download the Agile Template

In VS 2010 RC, open Process Template Manager from Team->Team Project Collection Settings.  Download the MSF for Agile Development template to your local file system.  A project template is a folder of xml files.  There is a ProcessTemplate.xml in the root and then a bunch of directories for things like Work Item Definitions and Queries, Reports, Shared Documents and Source Control Settings. 

image

Step 2: Copy the folder

My plan here is to make a new template with all of my modifications.  You can also just enhance update the MSF template.  However, I think it is cleaner when you start making modifications to make your own template.  So,copy the folder and name it with your new template name.

Step 3: Change Template Name

Open ProcessTemplate.xml and change the of the template.

Step 4: Copy the rdl of the Report you want to use a starting point

In my case,I copied Stories Progress.rdl and named the file Task Progress Breakdown.rdl.  I reviewed the requirements for the new report with some of the users here and came up with this plan.  Should show tasks and be expandable to show subtasks.  Should add Assigned To and Estimated Finish Date as 2 extra columns.

Step 5: Walkthrough the existing report to understand how it works

The main thing that I do here is try to get the sql to run in SQL Management Studio.  So, I can walkthrough the process of building up the data for the report.

After analyzing this particular report I found a couple of very useful things.  One, this report is already built to display subtasks if I just flip the IncludeTasks flag to 1.  So, if you are using Stories and have tasks assigned to each story.  This might give you everything you want. 

For my purposes, I did make that change to the Stories Progress report as I find it to be a more useful report to be able to see the tasks that comprise each story.  But, I still wanted a task only version with the additional fields.

Step 6: Update the report definition

I tend to work on rdl in visual studio directly as xml.  Especially when I am just altering an existing report, I find it easier than trying to deal with the BI Studio designer.  For my report I made the following changes.

  • Updated Fields
    • Removed Stack Rank and Replaced with Priority since we don”t use Stack Rank
    • Added FinishDate and AssignedTo
  • Changed the root deliverable SQL to pull @tasks instead of @deliverablecategory and added a join CurrentWorkItemView for FinishDate and Assigned to
SELECT cwi.[System_Id] AS ID FROM [CurrentWorkItemView] cwi
           
WHERE cwi.[System_WorkItemType] IN (@Task)
           
AND cwi.[ProjectNodeGUID] = @ProjectGuid
SELECT lh.SourceWorkItemID AS ID FROM FactWorkItemLinkHistory lh
           
INNER JOIN [CurrentWorkItemView] cwi ON lh.TargetWorkItemID = cwi.[System_Id]
           
WHERE lh.WorkItemLinkTypeSK = @ParentWorkItemLinkTypeSK
               
AND lh.RemovedDate = CONVERT(DATETIME, ~~9999~~, 126)
               
AND lh.TeamProjectCollectionSK = @TeamProjectCollectionSK
               
AND cwi.[System_WorkItemType] NOT IN (@DeliverableCategory)
  • Added AssignedTo and FinishDate columns to the @Rollups table
  • Added two columns to the table used for column headers
<Tablix Name=”ProgressTable”>
       
<TablixBody>
         
<TablixColumns>
           
<TablixColumn>
             
<Width>2.7625in</Width>
           
</TablixColumn>
           
<TablixColumn>
             
<Width>0.5125in</Width>
           
</TablixColumn>
           
<TablixColumn>
             
<Width>3.4625in</Width>
           
</TablixColumn>
           
<TablixColumn>
             
<Width>0.7625in</Width>
           
</TablixColumn>
           
              1.25in
           
           
              1.25in

           
</TablixColumn>
         
</TablixColumns>
  • Added Cells for the two new headers
  • Added Cells to the data table to include the two new values (Assigned to & Finish Date)
  • Changed a bunch of widths that would change the format of the report to display landscape and have room for the two additional columns
  • Set the Value of the IncludeTasks Parameter to 1
    <ReportParameter Name=”IncludeTasks”>
         
    <DataType>Integer</DataType>
         
    <DefaultValue>
           
    <Values>
             
    <Value>=1</Value>
           
    </Values>
         
    </DefaultValue>
         
    <Prompt>IncludeTasks</Prompt>
         
    <Hidden>true</Hidden>
       
    </ReportParameter>
  • Change a few descriptions on how the report should be used

This is the resulting report

image

I have attached the final rdl.

Step 7: Update ReportTasks.xml

Last step before the template is ready for use is to update the reportTasks.xml file in the reports folder.  This file defines the reports that are available in the template.

          <report name=”Task Progress Breakdown” filename=”ReportsTask Progress Breakdown.rdl” folder=”Project Management” cacheExpiration=”30″>
           
<parameters>
             
<parameter name=”ExplicitProject” value=”" />
            </
parameters>
           
<datasources>
             
<reference name=”/Tfs2010ReportDS” dsname=”TfsReportDS” />
            </
datasources>
         
</report>

Step 8: Upload the template

Open the process Template Manager just like Step 1.  And upload the new template.

That”s it.  One other note, if you want to add this report to existing team project you will have to go into reportmanager (the reporting services portal) and upload the rdl to that projects directory.

25 comments , permalink


12

Mar 10

Blog Rebranding



I have been spending more and more time on learning as much as I can on Agile Development and also have been fairly immersed in rolling out TFS 2010 in our environment.  I feel like it is time to talk about some of my experiences.  With that, I am rebranding my blog to focus on these topics.  I am going to start with a bunch of blogs on the process I have gone through getting TFS 2010 configured for our development teams.

Last week, Brian Harry was in our office and gave a great talk on the improved tools in TFS 2010 and how Microsoft uses the tools internally.  I followed that up with a high-level overview of the improved out of the box process templates and the process to customize them.  I am definitely very excited about the new features in 2010 and hopefully will keep up my motivation to blog about it.  I am writing my first post right now about the process I went through to build a task progress report based on the user story progress report in the MSF for Agile Development template.  Stay tuned…

7 comments , permalink


22

May 09

Walkthrough of Smiley.NET the FBML sample packaged with the Facebook Developer Toolkit



Smiley.NET is an FBML facebook application that uses the Facebook Developer Toolkit.  This sample is meant to mimick the Smiley sample produced by Facebook in PHP.  The idea behind this application is to show techniques for integrating your application within the Facebook Platform and also ideas for writing an FBML app in ASP.NET.  Before we walkthrough the code, I thought it would make sense to link to a couple of places that anyone writing a Facebook application should know.

Useful Links

The platform homepage – This includes links to various articles, tools and documentation

Anatomy of a Facebook Application – This walks through the various concepts that explain how an application fits into the facebook platform.  This article actually uses the smiley app as an example for several of the concepts.

How to write an ASP.NET Facebook Application – A great walkthrough explaining the basics of using the facebook developer toolkit.

Facebook Developer Toolkit – Open source project that wraps much of the Facebook platform to make it easier to use from .NET.

Facebook API Doc – Part of the facebook developer wiki where the various API methods are described.

Now let”s take a look at the code.  This sample is in the following directory in the codeplex source $/FacebookToolkit/Samples/FBMLCanvasSample.

The first thing to do is setup your facebook application at the facebook develop application.  This is where you will name your application and also get an API Key and Secret.  You really can”t do anything without your API Key and Secret.  After getting this setup, you can get Smiley.NET to function. 

I am going to look at the code first, and second describe the process of setting this application up to run.  So, to start making this application I created a new Web Application.  In this Web application, I added references to facebook.dll and facebook.web.dll from the toolkit.  The facebook assembly has the code that I can use to call the various facebook apis.  facebook.web assembly has some controls and code that I can leverage to make it much easier for my app to live in the facebook platform.

Setup.aspx (Application configuration and Template creation)

If you plan to have your application integrated with the feed system and the publisher, you will need to learn about how these work.  The links below are great starting points.

http://wiki.developers.facebook.com/index.php/Feed

http://wiki.developers.facebook.com/index.php/New_Design_Publisher

Now that you have the overview,  You will need to setup up the feed and publisher urls and create your templates.  To do this you can use the tools on the facebook developer site as described in the links below, or you can use the facebook REST api.  For this sample, we constructed a page that needs to be invoked one time after the application is deployed.  The page is config/setup.aspx.  This page has code to set the app properties, and create two feed templates.  After these are created,the web.config is updated with the ids that were generated and then we can start publishing.

Here is the code used to set the app properties,this is done in place of the edit settings feature at www.facebook.com/developers.

            var dict = new Dictionary<string, string>
           
{
               
{“application_name”,“Smiley.NET”},
               
{“callback_url”,callback},
               
{“tab_default_name”,“Smile.NET”},
               
{“profile_tab_url”,“mysmiles.aspx”},
               
{“publish_action”,“Smile at!”},
               
{“publish_url”,callback + “handlers/otherPublishHandler.aspx”},
               
{“publish_self_action”,“Smile!”},
               
{“publish_self_url”,callback + “handlers/publishHandler.aspx”},
               
{“info_changed_url”,callback + “handlers/infoHandler.aspx”},
               
{“wide_mode”,“1″}
           
};
           
this.API.admin.setAppProperties(dict);

Next we setup 2 feed template bundles.  Each template bundle contains a 1 line version, a short story version and a long version.  An app can have up to 100 templates.  In this case, we have one for what is published to the users feed (via New Smiley functionality) and 1 bundle for when a smile is sent to a friend via Send Smiley functionality.  I have included the code for creating one of the bundles here.

            var one_line_story = new List <string>{“{*actor*} is feeling {*mood*} today”};
           
var short_story = new List();
           
var short_story_template = new feedTemplate
                                   
{
                                       
TemplateTitle = “{*actor*} is feeling so {*mood*} today”,
                                       
TemplateBody = “{*actor*} just wanted to let you know that he is so {*mood*} today”,
                                       
PreferredLayout = “1″
                                   
};
           
short_story.Add(short_story_template);

            var full_story = new feedTemplate
                                   
{
                                       
TemplateTitle = “{*actor*} is feeling very {*mood*} today”,
                                       
TemplateBody =

{*emote*}
{*mood*}


                                   
};
           
if (string.IsNullOrEmpty(t1))
           
{
               
long bundle1id = this.API.feed.registerTemplateBundle(one_line_story, short_story, full_story);

 

Masterpage

Now, I create my masterpage.  In this case, I needed to pick between using a masterpage to handle the facebook authentication handshake and a basepage.  The masterpage is a little cleaner in my opinion and really fits exactly how I want this application to work.  In this project the master page is called FBMLMaster.master.  Let”s look at what this contains. 

It defines some placeholder labels for fbml content I want to write from the codebehind, it also defines the dashboard and tabs that will be the container for my application, lastly it defines a content area where each “page” will display its content. 

<asp:label runat=”server” id=”css” />
<
asp:label runat=”server” id=”js” />
<
asp:label runat=”server” id=”header” >
<fb:dashboard/>
<fb:tabs>
<fb:tab-item title=”Public”  href=”default.aspx” selected=”"/>
<
fb:tab-item title=”Home”  href=”home.aspx” selected=”" />
<
fb:tab-item title=”My Smiles”  href=”mysmiles.aspx” selected=”"/>
<
fb:tab-item title=”New Smiley”  href=”newsmiley.aspx” selected=”"/>
<
fb:tab-item title=”Send Smiley”  href=”sendsmiley.aspx” selected=”"/>
</
fb:tabs>
</asp:label>
<div id=”main_body”>
   
<asp:ContentPlaceHolder ID=”body” runat=”server”>
   
</asp:ContentPlaceHolder>
</div> 

The code-behind for the master page has a couple of critical things going on.  First it derives from facebook.web.CanvasFBMLMasterPage.  This is the base MasterPage that will handle the authentication handshake with facebook. 

The other 2 things that you will find here are.  1) the SetSelectedTab function.  This a function that can be called from each “page” such that we can set the selected property in the fb:tabs markup.  2) Insertion of the CSS and Javascript.  In the load of the master page, I am checking if the current page is being shown in a profile tab or if it is being shown in the application canvas.  When shown in the profile, I need to inject the CSS inline and hide the tabs, when in the canvas, I can just add a link reference that the fbml rendering engine at facebook can handle. 

 

        protected void Page_Load(object sender, EventArgs e)
       
{

            if (!string.IsNullOrEmpty(Request.Params["fb_sig_in_profile_tab"]))
           
{
               
header.Visible = false;
               
css.Text = FBMLControlRenderer.RenderFBML(“~/controls/FBMLCSS.ascx”);
           
}
           
else
           
{
               
css.Text = string.Format(“”, callback, cssVersion);
               
js.Text = FBMLControlRenderer.RenderFBML(“~/controls/FBMLJS.ascx”);
            }
       
}

The one thing you might notice is the call here to FBMLControlRenderer.RenderFBML.  The FBMLControlRenderer is a class defined in facebook.web.  This will just output raw FBML given a particular usercontrol.  I find writing fbml directly in the user control and using this utility as a very clean way to format and write my fbml (much better than trying to piece it together in a code-behind).  If you look at any of the UserControls in the controls directory of the Sample application you will see this in action.   There is another concept supported by the FBMLControlRenderer which relates to dynamic content.  But, we will look at that with the ProfileBox.ascx.

Now that we have MasterPage that is linking our CSS and JS and controlling the authentication flow, we now need to implement the pages that are associated with the tab described above.  The first page is Default.aspx.  This page is included to demonstrate one thing, and that is a page that is accessible without logging into facebook.   

Default.aspx (publically available canvas page)

The default page just includes some text within the content placeholder and then sets the RequireLogin property of the login and sets the Selected Tab.

 

        protected void Page_PreInit(object sender, EventArgs e)
       
{
           
Master.RequireLogin = false;
           
Master.SetSelectedTab(“default”);
       
}

A couple of important notes, this page is using the MasterType attribute so that we get a strongly typed instance of the master page in the code-behind without needing to cast. 

<%@ MasterType VirtualPath=“~/FBMLMaster.Master” %>

The other is that interaction with the master page needs to occur in Page_PreInit.

Home.aspx (Profile box, Application Info Sections and Extended Permissions)

This page demonstrates various things a canvas application can do to integrate with a user”s profile.  The first thing we are doing is in the page_load we are storing a variable on facebook to indicate whether we have setup this user before.  If we have we don”t need to do it again.  The other thing we are doing is creating the info section for this app and the profile box.  This is not a recommended approach, instead you should do this based on user action rather than just at load, but this just shows how to do it in the code-behind.  We will also see how to add a button to your app for accomplishing the same things. 

        protected void Page_Load(object sender, EventArgs e)
       
{
           
// You need to set info or profile box in order for the buttons on the page to show up.
            // Don~~t set them every time.
            var pref = this.Master.API.data.getUserPreference(1);
           
if (pref != “set”)
           
{
               
this.Master.API.profile.setInfo(“My Smiles”, 5, getSampleInfo(), this.Master.API.uid);
               
this.Master.API.profile.setFBML(this.Master.API.uid, null, getUserProfileBox(), null); 
               
this.Master.API.data.setUserPreference(1, “set”);
           
}
       
}

The profile box and info tab section are described in the anatomy of a facebook app.  They are shown below in this context

Profile Box

Image:Anatomy profileBox.png

Info Sections

Next will look at the actual content of Home.aspx.  This page demonstrates several more ways to integrate your application.  Here is a view of the page, we will then examine each section (how it is done and what it does)

image

The first section is a button for adding a profile box (as shown above) for this application.  The fbml for this button is


These are FBML tags that can prompt users for extended permissions from the canvas page.
<br />These will go away if you grant these permissions:<br />
<
fb:prompt-permission perms=”email”>Enable Email</fb:prompt-permission>
<br />
<
fb:prompt-permission perms=”infinite_session”>Enable Permanent Login</fb:prompt-permission> 

When the user clicks this link, they are prompted to allow the application to send emails, as shown here.

 

image

The last section shows how to have an input form that requests a specific permissions and submits some data.

<p>Upon submitting the form below, you will be prompted to grant email permissions (unless you~~ve already done so for this app):</p>
<form promptpermission=”email”><br />How often would you like to be notified of new smilies?<br /><input type=”text” name=”frequency”><input type=”submit” value=”Notify Me”></form></p>
 
MySmiles.aspx (canvas page with dynamic content)

This page is a simple content page, that formats some fbml to show what we have stored about the user.  This page shows a call to the data store api to get what we have stored.  This application stores all historical smiles in the UserPreference bucket of the datastore api.  There really isn”t anything else going on.  The interesting thing about this page, is that it doubles as the profile tab (if the user adds our app as the profile tab).  It doesn”t even have any code to handle this.  This was all done in the master page, so this page can just function and it will work whether it is in our application canvas or a profile tab.

NewSmiley.aspx (Feeds and Publisher)
This page shows how to publish to the user profile using a feed form, also it show a little bit about using FBJS and AJAX.  This page builds a grid of smiley images that when clicked will store your selected smile using the data store and then prompt to publish the selection to your wall.
 
First is the code used to store the selected Smile.  It is not obvious how this works.  First you must look at the BuildEmoticonGrid function in the BasePage.  This builds the grid and sets the javascript events to call our javascript functions.  In this case, we are using the EmoticonGrid that utilizes the javascript function called final which we will look at shortly.  In other places, this same grid is used without this function.  When we don”t use the function, we are demonstrating used the feed form instead of the javascript showFeedDialog function that is used in the final function.  More on that here, http://wiki.developers.facebook.com/index.php/Facebook.showFeedDialog.  The main difference between the versions of BuildEmoticonGrid are what javascript function is tied to onclick.  In this page, it is final. 
 
        public string BuildEmoticonGrid(Dictionary<string, string> moods, string callback, string suffix, bool useFinalFunction)
       
{
           
var ret = new StringBuilder();
           
ret.Append(
);
           
for (int i = 0; i < moods.Count; i++)
           
{
               
var js = string.Format(“final(~~{0}~~,~~{1}~~,~~{2}~~,~~{3}~~,~~{4}~~,~~{5}~~,~~{6}~~)”, FeedTemplate1, callback + “images”, “http://apps.facebook.com/” + suffix, callback, moods.ElementAt(i).Key, moods.ElementAt(i).Value, i);
               
if (!useFinalFunction)
               
{
                   
js = string.Format(“select(~~{0}~~,~~{1}~~,~~{2}~~)”, moods.ElementAt(i).Key, moods.ElementAt(i).Value, i);
               
}
               
if (i > 0 && i % 3 == 0)
               
{
                   
ret.Append(
);
               
}
               
ret.Append(string.Format(
{2}
{1}

, js, moods.ElementAt(i).Key, moods.ElementAt(i).Value, i));
           
}
           
ret.Append(

);
           
return ret.ToString();
       
}

Examining this code, the real key is that the js variable is assigned to the onclick property of each image.  Now, let”s look at the javascript.  If you remember in the master page, the javascript is injected into the FBML from FBMLJS.ascx.  Looking in this usercontrol, we find where the action is happening.
 
function final(template_id, image_src, base, callback, title, emote, id) {
 
select(title, emote, id);
 
var image = image_src + ~~/smile~~ + id + “.jpg”;
 
var template_data = { ~~mood~~: title,
      ~~emote~~
: emote,
      ~~mood_src~~
: image,
      ~~images~~
: [{ ~~href~~: base, ~~src~~: image}]
 
};

  var ajax = new Ajax();
 
ajax.responseType = Ajax.RAW;
 
ajax.post(callback+~~handlers/jsFeed.aspx~~, {~~picked~~:id});

  Facebook.showFeedDialog(template_id, template_data, ~~~~, [],
                         
function() {document.setLocation(base + ~~/mysmiles.aspx~~);});
}

There are two things going on.  First is an ajax call that is used to store the selected smile in the user”s data store.  This is done with a callback to jsFeed.aspx.  This class takes in the selected index and updated the user”s data store.

        protected void Page_Load(object sender, EventArgs e)
       
{
           
if (!string.IsNullOrEmpty(Request.Params["picked"]))
           
{
               
var picked = int.Parse(Request.Params["picked"]);
               
var moodList = JSONHelper.ConvertFromJSONArray(this.API.data.getUserPreference(0));
               
moodList.Insert(0, picked.ToString());
               
this.API.data.setUserPreference(0, JSONHelper.ConvertToJSONArray(moodList));
               
var oldCount = 0;
               
if (!string.IsNullOrEmpty(this.API.data.getUserPreference(2)))
               
{
                   
oldCount = int.Parse(this.API.data.getUserPreference(2));
               
}
               
this.API.data.setUserPreference(2, (oldCount + 1).ToString());
           
}
       
}

After this is done, the final function used some FBJS to pop a publisher dialog to allow the user to publish data.  This is using passed in template id and the Facebook.showFeedDialog javascription function.  We pass mysmiles as the return page after the publisher dialog is complete.

SendSmiley.aspx (Multifeed Story Form)

This page is a demostration of how to publish stories to the wall of one of the user”s friends.  This will use the other publisher that you have specified in your application properties.  In this case, our other publisher (that handles publishing to friend”s walls is in multiFeedHandler.aspx).  To learn more about the multi feed form, read the following wiki page, http://wiki.developers.facebook.com/index.php/MultiFeedStory_form.

In this case, the send smiley page is very simple.  Set the action of the multifeed form to the multiFeedHandler and display the Emoticon grid that is not using the final javascript function.  In this case, the onclick of the image will just set the style to show which is clicked, and the multi feed form will submit it to the selected friends. 

protected void Page_Load(object sender, EventArgs e)
       
{
           
multiFeedHandler = string.Format(“{0}handlers/multiFeedHandler.aspx”, Master.callback);
           
grid.Text = BuildEmoticonGrid(getOtherMoods(), Master.callback, Master.suffix,false);

        }

The only other thing to note, is that a multi friend selector is included in this page to allow the user to select the friends they want to target the smiley. 

image

Conclusion 

Creating an fbml application that really leverages all of the avenues of integration with facebook is not trivial.  Hopefully, this sample application and the source code avaiable at codeplex will help people overcome the learning curve.  I am going to do my best to support the toolkit better and provide some more articles in the upcoming weeks.  In the next article, I want to examine leveraging facebook connect with the toolkit.  I imagine that it will lead to some updates to the toolkit.

16 comments , permalink


20

Nov 07

Facebook Developer Toolkit Explained at CNUG



I just finished presenting to the Chicago .NET User Group on Facebook Development using the Microsoft stack. I focused primarily on the Facebook Developer Toolkit for obvious reasons (it is just what I know). The session covered an overview of the Facebook API and the Facebook Platform. We then talked in depth about using the Facebook Developer Toolkit to leverage the Facebook API and to write Canvas pages hosted within the Facebook Platform. Thanks to my colleague Jonathan Schuster who did the code demos and saved me a bunch of prep time. I was also able to demo leveraging Silverlight 1.1 on a Facebook IFrame Canvas page.

This is part of the deck where I described an overview of the Facebook Platform.

image

If you are new to the Facebook Platform, I~~d recommend the recording we made of the session (linked at the end of this post) or check out the interview we did on Thirsty Developer

The turn out was good. I think we had 40+ people and most were new to Facebook development. It was fun to introduce this platform to a new group of .net developers. If you are interested in the presentation, the slides, demos and a video of the presentation can be accessed at clarityTV.

6 comments , permalink


20

Nov 07

Facebook Developer Toolkit Version 1.3 Released



My thanks go out to my colleague Jonathan Schuster, who took over support of the Facebook Developer Toolkit for the past few weeks. He was able to push his way through a bunch of enhancements and bug fixes that the users have been waiting very patiently for.

This release marks a good milestone for the Toolkit as the majority of known issues with the support of Canvas applications are solved. In my opinion, the canvas support is now very solid and will really ease the learning curve for new developers who want to leverage the toolkit.

One of the big features of Release 1.3 is support for the compact framework. Many thanks to Peter Foote who dedicated a bunch of time to work on these features. For those of you interested, the release contains the following items.

image

Thanks to all of the people who have kept this project alive as I was pulled away. Pretty cool. We have had close to 500 downloads already. I am hoping to re-engage and help add support for new things that Facebook is releasing.

0 comments , permalink


26

Jul 07

Hosting Vista File Previews in Managed Code



As part of my work on the Coding4Fun Developer Kit 2008, I created a WinForm control encapsulating the flow to display file previews. The host is dependent on an improved version of Stephen Toub~~s framework, originally published here. My enhancements were basically to make the COM wrapper classes public so that they can be used by the Managed PreviewHandlers and also by my Preview Handler Host. The source for this project including the updated framework, Stephen~~s sample preview handlers, my host control and a sample application using the host control are available here. Also, they can be downloaded from the codeplex project for the Coding4Fun Developer Kit 2008.

A couple of quick notes before I describe how the managed preview handler host works.

  1. For any of this to work, the C4F.DevKit.PreviewHandlerFramework.dll needs to be installed in GAC.
  2. Also, this host will work with all non-managed preview handlers and any managed preview handlers that were built against the PreviewHandlerFramework mentioned above. Any Managed Preview Handlers that were compiled using Stephen~~s original framework or another method will not work with this host.

To host the results generated by any registered file preview handler in managed code, the PreviewHandlerFramework”s COM Wrappers are leveraged. In addition, part of this host needs to look up the preview handler that is currently registered with a particular file extension. To accomplish this, the PreviewHandlerHost leveraged the registry code from Stephen Toub”s Preview Handler Association Editor (http://blogs.msdn.com/toub/archive/2006/12/14/preview-handler-association-editor.aspx). With the code to find the registered handler in hand, we constructed a control to implement the preview handler Data Flow as shown below (all of this code is part of PreviewHandlerHost project,PreviewHandlerHostControl.cs):

  • Declare an object that is the PreviewHandler (this will be cast to different COM Interfaces as needed)
  • Unload any existing previews before generating a new preview
    • Call Unload of IPreviewHandler Interface (dDefined in PreviewHandlerFramework as a wrapper to existing COM interface)

Visual C#

private object _comInstance = null; private void GeneratePreview() { if (_comInstance != null) { ((IPreviewHandler)_comInstance).Unload(); }

Visual Basic

Private _filePath As String Private Sub GeneratePreview() If Not _comInstance Is Nothing Then CType(_comInstance,IPreviewHandler).Unload() End If
  • Build a RECT struct using the bounds of the visible area where the preview handler can draw. In this case, that is the full bounds of the PreviewHandlerHostControl

Visual C#

RECT r; r.top = 0; r.bottom = this.Height; r.left = 0; r.right = this.Width;

Visual Basic

Dim r As RECT r.top = 0 r.bottom = Me.Height r.left = 0 r.right = Me.Width

  • Find the CLSID of the preview handler registered for the file extension of the file using registry lookup. This is typically done by looking in the registry under HKEY_CLASSES_ROOT%file_extension%shellex{8895b1c6-b41f-4c1c-a562-0d564250836f}. This Registry key will have a value pointed to the Class ID (CLSID) of the COM registration of the registered preview handler. For more information about how preview handlers can be found in the registry, see this article.
  • Create an instance of the preview handler using Reflection and the CLSID found in the registry.

Visual C#

Type comType = Type.GetTypeFromCLSID(new Guid(handler.ID)); _comInstance = Activator.CreateInstance(comType);

Visual Basic

Dim comType As Type = Type.GetTypeFromCLSID(New Guid(handler.ID)) _comInstance = Activator.CreateInstance(comType)

  • Call the appropriate initialize for the create preview handler (either passing in a stream or filepath)
    • If the preview handler is a stream previewhandler, using a COM IStream Wrapper to handle Stream marshalling to COM

Visual C#

if (_comInstance is IInitializeWithFile) { ((IInitializeWithFile)_comInstance).Initialize(_filePath, 0); } else if (_comInstance is IInitializeWithStream) { if (File.Exists(_filePath)) { StreamWrapper stream = new StreamWrapper(File.Open(_filePath, FileMode.Open)); ((VSExpressDevPack.PreviewHandlerFramework.IInitializeWithStream)_comInstance).Initialize(stream, 0); } else { throw new Exception(File not found); } }

Visual Basic

If TypeOf _comInstance Is IInitializeWithFile Then CType(_comInstance, IInitializeWithFile).Initialize(_filePath, 0) ElseIf TypeOf _comInstance Is IInitializeWithStream Then If File.Exists(_filePath) Then Dim stream As StreamWrapper = New StreamWrapper(File.Open(_filePath, FileMode.Open)) CType(_comInstance, VSExpressDevPack.PreviewHandlerFramework.IInitializeWithStream).Initialize(stream, 0) Else Throw New Exception(File not found) End If End If

  • Call SetWindow on the PreviewHandler, passing in a handle to the control and the bounds (RECT created earlier)

Visual C#

((IPreviewHandler)_comInstance).SetWindow(this.Handle, ref r);

Visual Basic

CType(_comInstance, IPreviewHandler).SetWindow(Me.Handle, r)
  • Call DoPreview on the PreviewHandler

Visual C#

((IPreviewHandler)_comInstance).DoPreview();

Visual Basic

CType(_comInstance, IPreviewHandler).DoPreview()

If you are interested in more information, the zip file included with this project has all of the source and a document describing a walkthrough of using this control. Additionally, the Coding4Fun Developer Pack 2008 Vol.1 Codeplex project has all the info and will also have any fixes/enhancements.

7 comments , permalink


26

Jul 07

Coding4Fun Developer Kit 2008 Vol.1 Beta Released on Codeplex



Recently, I have been spending most of my time helping put together the Coding4Fun Developer Kit that was released today on Codeplex. This is a Kit put together by Microsoft to open up many of the new and powerful APIs avaiable in Vista and Visual Studio 2008 to enable simple programming interfaces that can be used from managed code.

This developer kit contains .net wrappers and sample projects for the following Vista APIs

  • Bluetooth
  • Contacts
  • Digital Sound Recording
  • Messaging/Email
  • Picture Sharing
  • Picture Acquisition
  • Power Management
  • Preview Handlers
  • Feeds
  • Desktop Search

I made two big contributions to this developer kit. The first was building the Preview Handler Wrapper. This Wrapper included enhancing the managed preview handler framework built by Stephen Toub and published in the January Edition of MSDN Magazine. In addition, I wrote a managed preview handler host, to enable displaying any preview handler within a .net winform application. Watch for my next post describing, Hosting File Previews In Managed Code. My other contribution to the project was pulling the various projects together and building the installer. I used WIX. It was a tedious process at times, but ultimately pretty effective. I promise to write another post detailing my experience with WIX and what I did to put this installer together.

Check out the codeplex site for the Coding4Fun Developer Kit 2008 vol.1. Definitely some cool and interesting stuff.

1 comment , permalink


6

Jul 07

SQL 2005 Performance Tuning using DMVs – Part 4 of 7 – I/O Health



In my previous 3 posts in this series, I went through an introduction to Dynamic Management Views and an in depth look at how DMVs can be used to analyze and pinpoint CPU bottlenecks. In today~~s post we will take a look at using DMVs for analyzing I/O Health and pressure.

You can use the following DMV query to find currently pending I/O requests. You can execute this query periodically to check the health of I/O subsystem and to isolate physical disk(s) that are involved in the I/O bottlenecks.

SELECT database_id, file_id, io_stall, io_pending_ms_ticks, scheduler_address FROM sys.dm_io_virtual_file_stats(NULL, NULL)t1 INNER JOIN sys.dm_io_pending_io_requests as t2 ON t1.file_handle = t2.io_handle

If you find, that you regularly have a high number of pending I/O requests, you can use the following query to determine which SQL batches use the most I/O.

SELECT TOP 5 (total_logical_reads/execution_count) as avg_logical_reads, (total_logical_writes/execution_count) as avg_logical_writes, (total_physical_reads/execution_count) as avg_phys_reads, Execution_count,statement_start_offset as stmt_start_offset,st.[text], qp.query_plan FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp ORDER BY (total_logical_reads + total_logical_writes) Desc

If you are troubleshooting blocked I/O realtime, you can use dm_tran_locks and dm_waiting_tasks to determine what sql is blocking and what is waiting.

SELECT t1.resource_type, ~~database~~=db_name(resource_database_id), ~~blk object~~ = t1.resource_associated_entity_id, t1.request_mode, t1.request_session_id, t2.blocking_session_id FROM sys.dm_tran_locks as t1 INNER JOIN sys.dm_os_waiting_tasks as t2 ON t1.lock_owner_address = t2.resource_address and t1.request_session_id = t1.request_session_id

The last thing to check when analyzing I/O is the utlization of tempDB. You can use dm_db_file_space_usage to determine the amount of space that is being used in tempdb by user_objects, internal_objects and the version_store.

SELECT SUM (user_object_reserved_page_count)*8 as user_objects_kb, SUM (internal_object_reserved_page_count)*8 as internal_objects_kb, SUM (version_store_reserved_page_count)*8 as version_store_kb, SUM (unallocated_extent_page_count)*8 as freespace_kb FROM sys.dm_db_file_space_usage WHERE database_id = 2

That~~s it for this edition, in the next installment we will look at finding Problem Queries.

The code from this post is available here.

2 comments , permalink


6

Jul 07

Facebook Developer Toolkit Version 1.2 Released



I have been spending most of time working on the Facebook Developer Toolkit and monitoring our codeplex site. Things have been going pretty, the response has been pretty positive and the help from the other site contributors has been great. We even just became the 10th most popular project on CodePlex. Which is a pretty cool accomplishment and pretty impressive company.

Today, we released Version 1.2 of the Toolkit.

Included in this release are:

  • Refactored FacebookService
  • Added AsyncFacebookService
  • Refactored Parsers and Entities into their own directory and namespace
  • Added improved photo api
  • Added Canvas Base pages to Facebook.WebControls
  • Added Canvas samples to Facebook.WebControls
  • Added IFrame Ajax sample
  • Added IFrame Silverlight Example
  • Updated to new notifications API *INTERFACE CHANGE*
  • Updated PublishStory and PublishAction interfaces *INTERFACE CHANGE*
  • Updated CreateAlbum interface to return created Album *INTERFACE CHANGE*
  • Added SetFBML override taking in userid
  • Added small and big picture url and bitmap to photo and user
  • Added GetFriendsNonAppUsers method
  • The major change is the Canvas base pages, these should help new developers solve the riddle of building Facebook Canvas applications.

    Thanks to everyone who helped with code and feedback. I think we continue to make good progress on this project. You can download the release or documentation here.

    0 comments , permalink