WELCOME

This blog is where I post about my consulting work with Microsoft Technologies, and other random tidbits that don't fit in my Photo Blog or my Iraq Blog.

Friday, December 4, 2009

SetPropertyValues never called in custom ProfileProvider

I've been writing a custom ASP.NET MembershipProvider, RoleProvider, and ProfileProvider from scratch with Amazon SimpleDB as a backend. Everything went swimmingly with Membership and Roles, but I've spent an embarassing amount of time fighting with Profile...

Profile's underlying object model is complex and less than intuitive. The challenge for me was trying to figure out what things had to be implemented in order to get basic functionality working.

The major roadblock I ran into was that at the point that I was code complete and everything seemed like it "should" have been working I couldn't get anything to save. No errors, but nothing was saving.

All Profile saves go through SetPropertyValues and when I set a break point on my overridden version of this method it was just never getting hit.

After hours of trashing about I finally found the answer in this thread: http://forums.asp.net/t/635411.aspx

The gist of the problem is that before every save Profile calls GetProfileValues, and if the result returned by GetProfileValues isn't properly populated SetPropertyValues just doesn't get called. Highly unintuitive.

Here is the quote from the thread that finally solved the problems for me:

"Basically, somewhere in GetPropertyValues, there should be code new'ing up SettingsPropertyValue instances that looks like:

SettingsPropertyValue sv = new SettingsPropertyValues(SettingsPropertyInstanceGoesHere);

You get the SettingsProperty instance from the SettingsPropertyCollection that is passed in as a parameter to the GetPropertyValues method."

When I'm done these providers will be published on Codeplex as part of my ScrappyDB C# library for SimpleDB.

Sunday, November 29, 2009

Happy Holidays!


, originally uploaded by ScrappyDog.

Family 2.0 portrait at "the Farm" in Grand Marais over Thanksgiving. Photo by Gramma Betsy.

Wednesday, November 11, 2009

Question from a friend: I need a more "professional" email address, but I don't want to give up my Gmail address

Question of the day from a friend: I'm applying for jobs, and I need a more "professional" email address, but I don't want to give up my Gmail address, and I don't want to have to log into two different accounts all the time to check my mail.

Example current address: binge.drinker@gmail.com
New email address: john.a.doe@gmail.com

No problem!
  1. First step create the new Gmail account.
  2. Then you need to pick which mailbox you want to use as the primary one that you are going to login to (you probably want to keep using the existing one, because it has all your old mail).
  3. Go into the new email box and click on the "Settings" link at the top right.
  4. Select the "Forwarding and POP/IMAP" tab.
  5. Select "Forward a copy of incoming mail to" and enter the email address of the old account.
  6. I would recommend setting "archive Gmail's copy".

You are now done with step one. All email sent to the new address should start showing up in you old inbox.
Now you want to be able choose which address to use when you send/reply to email in your old inbox.
  1. Go into the old email box and click on the "Settings" link at the top right.
  2. Select the "Accounts and Import" tab.
  3. Go to the "Send mail as:" section and click the "Send mail from another address" button enter the other (new) email address.
  4. Check the "Reply from the same address the message was sent to" option.
  5. Gmail is now going to send you an email to confirm that you own the other address, you will need to click a link in the email to confirm.
You should be all set.

Now when you are composing an email you will notice there is "change" link after the "From:" address. You can use this to pick which address you would like your email to be from.

Monday, November 9, 2009

ScrappyDB: C# Object Mapper for Amazon SimpleDB

I've been working on a new C# Object Mapper for Amazon SimpleDB for a few months to provide an "infinitely" scalable back end for a personal web project, and today I'm releasing it on CodePlex.

http://scrappydb.codeplex.com/

Project Description

ScrappyDB is a simple object mapper for storing .NET classes and collections in Amazon SimpleDB. It is currently under active development to support the needs of a specific website. As such it only provides functionality to support the needs of one "customer", this means that there are many "obvious" use cases and data types that are not yet supported... because we didn't need them. But we think other people may find it useful, so we are sharing it here...

Why create an new tool instead of using one of the existing .NET tools for SimpleDB?

In particular:
  • Simple Savant http://simplesavant.codeplex.com/ (Simple Savant is a great tool and definitly a more mature code base. We would recommend that you investigate it first before considering ScrappyDB.)

Features that we felt were important for our implementation:
  • Support for multi-value attributes (using arrays or arraylists).
  • Support for nested objects and relationships (in particular cases where a custom class has a property that is a collection of some other custom class).
  • Integrated support for web caching for performance.
  • Location data (in particular the ability to do proximity searches "show me all records within 5 miles of X").

Things that we did NOT feel were important for our implementation:
  • Support for all .NET data types (we only support a subset of "common" data types, but there is no reason you can't enhance it to support the one you need).
  • Update caching to work around "eventual consistency" (if you don't have a full understanding of what eventual consistency means take the time to learn about it before you decide whether SimpleDB is a viable platform for your data).

About the source code
  • To do what it does ScrappyDB makes extensive use of some painful reflection.
  • The code does not follow any identifiable design patterns and it doesn't follow any of the latest inversion of control fashions: "I'm just a caveman, and I'm not familiar with your modern ways..."

Known Issues:
  • Current code is definitely ALPHA, has not had any significant production use.
  • Relationship logic is lightly testing, is probably buggy and is likely to see some significant refactoring.
    • We are planning to add a second relationship type that uses multivalued attributes for "1 to few" relationships ("1 to many" relationships use an intermediate relationship "table" which is slower).

Dependencies
Documentation
  • Currently the primary developer documentation for ScrappyDB is the unit tests included with the source code.

But here are a few basic examples to help you get started:


Basic Save
            var db = new DB();
var o = new MyClass {Id = Guid.NewGuid, TestProperty = "HelloWorld"};
db.Save(o);

Basic Load by Id
            var result = db.Load(testId);

Save a Collection
            var a = new ScrappyDbCollection();
a.Add(new TestItem() { Id = Guid.NewGuid(), TestString = "test1" });
a.Add(new TestItem() { Id = Guid.NewGuid(), TestString = "test2" });
a.Add(new TestItem() { Id = Guid.NewGuid(), TestString = "test3" });

a.Save();

Query a Collection
            var b = new ScrappyDbCollection();
b.QueryCollection(" TestString = 'test2' ");

Tuesday, September 1, 2009

WSOD Google Style (White Screen of Darn)

My Google Apps email server is down at the moment, so I thought I would share the error message... Why? "Because it was there."

FYI: There is an application status page at Google for major apps: http://www.google.com/appsstatus

UPDATE: Great post on the Gmail Blog detailing what caused today's outage: http://gmailblog.blogspot.com/2009/09/more-on-todays-gmail-issue.html


Google

Error

Server Error

The server encountered a temporary error and could not complete your request.
Please try again in 30 seconds.

Thursday, June 18, 2009

Happy Early Father's Day To Me!


300_9227, originally uploaded by ScrappyDog.

The kids all got matching shirts (including one for me) for a Father's Day picture...

Thursday, June 11, 2009

MVVM Questions: Can a View Model close a window and other puzzlers

Many sample WPF applications written using MVVM (Model - View - View Model) only use a single Window, but the LOB (Line Of Business) applications I’ve been working on use LOTS of windows for different business tasks, and this has brought up a number of interesting questions about the “right” or “best” or “most practical” way to manage multiple Windows in a WPF application using MVVM?

Questions:

  1. Does a Window create it’s View Model?
  2. Or does the View Model create it’s Window?
  3. Or does “something else” create the View Model and the Window and then bind them together?
  4. How do you close a Window? 
  5. Can a View Model close itself and it’s Window?

Our Answers:

  1. We created a “Window Service” which is basically a Singleton with a Dictionary of all the open Windows and View Models in the application, and a few related methods to deal with opening and closing Windows .
  2. To open a Window you supply the Window Service with Window and a View Model.  The Window Service deals with binding the two together, showing  the Window, and then keeping track of the open Windows.
  3. If a user (or something else) tries to close a Window we catch the Window_Closing event  using AttachedCommandBehavior (see XAML below) and call a command on the View Model Base Class to give the View Model control over the closing event.
    <acb:CommandBehaviorCollection.Behaviors>
    <acb:BehaviorBinding Event="Initialized" Command="{Binding Path=Window_InitializedCommand}" />
    <acb:BehaviorBinding Event="Activated" Command="{Binding Path=Window_ActivatedCommand}" />
    <acb:BehaviorBinding Event="Closing" Command="{Binding Path=Window_ClosingCommand}" />
    </acb:CommandBehaviorCollection.Behaviors>



  4. View Models have the ability to close themselves (and their related Window) by calling the Window Service.

Wednesday, June 10, 2009

A simple method of binding the selected values of a list in WPF with MVVM

Using the MVVM pattern in WPF applications simplifies some aspects of developing and testing WPF applications, but it add quite a bit of complexity to others…

One interesting challenge I faced recently with MVVM was how to achieve two way binding of the selected values of a ListBox to a collection in a view model.  I would like to share an approach to solving this challenge using Styles and Databinding.

It’s easy to bind the values of a collection in a view model to a list, but the challenge is that you want the view model to be aware of user selections in the list without having to use traditional events an code behind.

You also want to be able to change the selected items in the view model and have those changes reflected in the UI. In my sample code (below) this is demonstrated by the “Select All” checkbox, which modifies the select items in the view model.

The key to this approach is that entities in the collection you are binding to have to have a boolean “IsSelected” property (you can name it whatever you like).  And then you create a Style to bind the IsSelected property of the ListBoxItem to the IsSelected property of the bound entity.  See the XAML sample code below:

<ListBox ItemsSource="{Binding PersonCollection}" 
SelectionMode="Multiple" >

<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
</Style>

<DataTemplate DataType="{x:Type MultiSelectMvvm:Person}">
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Name}"/>
<Label Content="{Binding IsSelected}"/>
</StackPanel>
</DataTemplate>
</ListBox.Resources>

</ListBox>

<CheckBox IsChecked="{Binding SelectAll}" Margin="3">
Select All
</CheckBox>


Here is the ViewModel code:



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace MultiSelectMvvm
{
public class Window1ViewModel
{
ObservableCollection<Person> personCollection;
public ObservableCollection<Person> PersonCollection
{
get
{
if (personCollection == null)
{
personCollection = new ObservableCollection<Person>();
}
return personCollection;
}
set { personCollection = value; }
}

private bool selectAll;
public bool SelectAll
{
get
{
return selectAll;
}
set
{
selectAll = !selectAll;
foreach (var person in personCollection)
{
person.IsSelected = selectAll;
}
}
}
}


public class Person : INotifyPropertyChanged
{
public string Name
{
get;
set;
}

private bool? isSelected;
public bool? IsSelected
{
get
{
return isSelected;
}
set
{
isSelected = value;
NotifyPropertyChanged("IsSelected");
}
}

public event PropertyChangedEventHandler PropertyChanged;

private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
}


FYI: Marlon over at C# Disciples wrote a recent blog post about this: Sync Multi Select Listbox with ViewModel.  His approach uses Attached Properties.

Tuesday, June 9, 2009

Microsoft paying to advertise Bing on Google?!?!

I found this hilarious on a variety of levels: Microsoft is paying Google to place ads for it's new Bing search engine on Google (see the screen grab from my Gmail inbox below).

It has got to cause some serious pain at Microsoft to pay this bill. Did they use Steve Balmer's credit card to setup the Adwords account?

Who is the person at Google that signed off on this? It takes some balls to happily place ads for your competition on your own site.

Thursday, April 9, 2009

Silverlight 3 plus OS X plus Firefox = bad juju?

I'm getting the following weird error on Apple OS X when I try to access a site that (I think) is using the Silverlight 3 beta using Firefox:



Key point: the website says I have the latest version of Silverlight installed, but I'm getting a message box that says my version of Silverlight has "expired"... not very helpful...

UPDATE: The problem site I am trying to access is: http://blogs.msdn.com/silverlightws/archive/2009/04/08/using-wcf-services-from-silverlight-in-azure.aspx

UPDATE #2: Manually installing the Silverlight 3 Beta did solve the problem (the error message was still incredibly unhelpful...)

Tuesday, March 31, 2009

Double-clicking on a ListBox in MVVM

Here is a quick code snippet that demonstrates doubleclicking on a WPF ListBox in MVVV. Note: This is using AttachedCommandBehavior V2.


<
ListBox Name="MyListBox">

<ListBox.Resources>

<Style
TargetType
="{x:Type ListBoxItem}">

<Setter
Property
="IsSelected"
Value
="{Binding
Path
=IsSelected, Mode=TwoWay}"/>

<Setter
Property
="acb:CommandBehavior.Event"
Value
="MouseDoubleClick" />

<Setter
Property
="acb:CommandBehavior.Command"

Value="{Binding ElementName=Window1,
Path
=DataContext.MyDoubleClickCommand}" />

<Setter
Property
="acb:CommandBehavior.CommandParameter"
Value
="{Binding}"
/>

</Style>

   


</
ListBox.Resources>

</ListBox>

Key points to note:
  • Setting the CommandParameter to "{Binding}" passes the item that is bound to this ListBoxItem as a parameter to the command we are calling (answering the question: "What item was double clicked?".
  • Using a Style is a quick way to insert the stuff we want into each ListBoxItem.
  • This example is also binding IsSelected so that we can determine the SelectedItem(s) from within the view model (this isn't required to make double click work... I just thought it was interesting to leave it in the code snippet since it took me a while to figure it out...)

Wednesday, February 25, 2009

Why is my WPF Popup black and how do I get it positioned properly?

A quick WPF tip:

Problem: I was trying to create a cool OS X style semi-transparent round cornered popup but no combination of setting Background=Transparent or Opacity<1 would give me anything but a big square cornered black box in the wrong part or the screen.

Solution: You need to set the AllowsTransparency property on the Popup to True, and set the PlacementTarget and Placement properties to control the position the Popup opens in.


<Popup x:Name="RecipeSourcePopup"

               PlacementTarget="{Binding ElementName=MainStackPanel}"

               Placement="Center" AllowsTransparency="True"

               HorizontalAlignment="Center" VerticalAlignment="Center" >

Thursday, February 12, 2009

Email Management Tip: Automatically flagging sent email that requires a followup

Here's a great email management tip that I got from an "aunt" of mine:

How often do send an email that requires a response from somebody else, or that you want to followup on later? How often does the other person fail to reply? How often do you fail to remember to follow up?

So here's the tip: On any email that requires a followup, cc: it to YOURSELF and then create an Inbox rule in Outlook or filter in Gmail (I love Gmail) that saves the sent message to folder/label named "Followup Required".

Wala! An automagic task list!

And you can add tasks for yourself the same way... just email yourself a note... it doesn't have to be a reply.

And if you thought that was interesting you might like this old post on the rest of my email management strategy.

Wednesday, February 11, 2009

Great article on using: WCF in Silverlight 2

Here's a great article I just found on using WCF in Silverlight 2. It really should be at the top of any Google search remotely related to WCF and Silverlight and so here's a little link love to boost it up the list:

http://www.netfxharmonics.com/2008/11/Understanding-WCF-Services-in-Silverlight-2

Friday, February 6, 2009

Applying (and blocking) global styles in WPF/Silverlight

I've been digging the ability to globally set default styles in a WPF/Silverlight application. For example I have a file named GlobalStyles.xaml that contains the default styles for all windows in my app:


<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <!--Default styles that will apply to any object of the specified type (if it doesn't have style set locally)-->

    <Style TargetType="Button">

        <Setter Property="FontSize" Value="11"/>

        <Setter Property="FontWeight" Value="UltraBold"/>

        <Setter Property="Button.Margin" Value="10,0,10,0" />

        <Setter Property="Button.Padding" Value="3"  />

        <Setter Property="Button.Height" Value="25" />

        <Setter Property="Button.MinWidth" Value="75" />

    </Style>

    <Style TargetType="Label" >

        <Setter Property="Margin" Value="10,0,10,0" />

        <Setter Property="FontSize" Value="11"/>

        <Setter Property="HorizontalAlignment" Value="Left"/>

        <Setter Property="VerticalAlignment" Value="Top"/>

        <Setter Property="MinWidth" Value="75"/>

    </Style>


This is all great EXCEPT when you DON'T want your groovy new global styles to apply to a window or specific element on your page. In my specific case the global style for "Button" was totally hosing the display of the WPFToolkit DataGrid which is itself composed of lots of WPF Buttons.

The answer is to put an EMPTY Style into the Resources section of the page or control that you want to block the global style from applying to. Here is the DataGrid specific example:


<toolkit:DataGrid.Resources>

    <!--The following line overrides (blocks) the global default styles

    for "Button" from effecting the datagrid -->

    <Style TargetType="Button" />

</toolkit:DataGrid.Resources>


You can do the same thing for the whole Window like this:


<Window.Resources>

        <Style TargetType="Button" />

</Window.Resources>

Wednesday, February 4, 2009

Simple Asynch Demo in Silverlight

Here's a demo that shows a very simple lambda and delegate based approach to making async calls in Silverlight.




Thanks to MichealGG for the code. See his response to my question on StackOverflow here: http://stackoverflow.com/questions/508177/implementing-a-nested-asynch-call-stack-scenario-in-net


<UserControl x:Class="SilverlightTestApp.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Name="ResultsTextBlock"
Width="400" Height="300"
TextWrapping="Wrap"/>
</Grid>
</UserControl>




using System;

using System.Threading;

using System.Windows;

using System.Windows.Controls;

 

 

namespace SilverlightTestApp

{

    public partial class Page : UserControl

    {

        public Page()

        {

            InitializeComponent();

 

        }

 

        private void AsynchDemo()

        {

            ResultsTextBlock.Text = "";

            ResponseWriteLine("BEGIN: AsynchDemo()");

 

            AsyncHelp(

                () => SlowDateTime("The time is now:  "),

                ex => ResultsTextBlock.Text += ex.ToString(),

                bla => ResultsTextBlock.Text += bla.ToString()

                );

            ResponseWriteLine("CALLED: SlowDateTime()");

 

            Action<string> r = ResponseWrite;

 

            for(int x = 0;x<100;x++)

            {

                AsyncHelp(

                    () => RandomSleep(x),

                    ex => ResultsTextBlock.Text += ex.ToString(),

                    r);  //use a delegate instead of a lambda expression

            }

 

            ResponseWriteLine("END: RandomSleep() x 100");

        }

 

        public string RandomSleep(int input)

        {

            Random r = new Random();

            int t = r.Next(10000);

            Thread.Sleep(t);

            return input.ToString() + "."; ;

        }

 

        public void ResponseWrite<T>(T result)

        {

            ResultsTextBlock.Text += result.ToString();

        }

        public void ResponseWriteLine<T>(T result)

        {

            ResultsTextBlock.Text += result.ToString() + Environment.NewLine;

        }

 

        public string SlowDateTime(string text)

        {

 

            Thread.Sleep(5000);

            return text + DateTimeOffset.Now.ToString();

        }

 

        public void AsyncHelp<T>(Func<T> f, Action<Exception> econt, Action<T> cont)

        {

            var t = new Thread((_) =>

            {

                try

                {

                    var res = f();

                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() => cont(res));

                }

                catch (Exception ex)

                {

                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() => econt(ex));

                }

            });

            t.Start();

        }

 

        private void Button_Click(object sender, RoutedEventArgs e)

        {

            AsynchDemo();

        }

    }

}

Tuesday, January 27, 2009

Windows 7 Beta plus Visual Studio Express Editions: Happiness!

I installed Windows 7 Beta on a virtual machine as soon as it came out, and have been impressed with the clean feel and low resource utilization.

To actually test it a little bit I decided I should use it for some real development, and so I installed the C# and Web versions of Visual Studio 2008 Express Edition and checked out a couple of existing projects from svn.

I'm impressed with both Windows 7 and the Visual Studio 2008 Express Editions (I had never actually tried to use them before)!  Other than missing Resharper, I'm not sure that I really use that much functionality in Visual Studio 2008 Team Suite at all...

Best of all it seems really fast on a VM with only 1gb of ram!

Tuesday, January 20, 2009

Deleting 4,000 Gmail groups... (or: Repairing Soocial replication damage)

I tried out Soocial.Com last week. Soocial is a new service that advertises "Hassle-free contacts". It claims it can synch ALL your contacts across multiple applications and multiple platforms while it perfectly toasts your morning bagel.

In reality it's a young beta application that launched a little too soon, and you should use it with extreme caution. I'm sure it's going to be great when they work the bugs out, but today it still has some "issues".

In my case it created over 4,000 groups in my Gmail account over the space of a couple days before I noticed. NOT a happy thing!

Gmail doesn't have any sort of bulk delete option, and deleting all 4,000 of them one at a time could have taken years... So I downloaded the Google API and wrote a little .NET application to do it for me. Nerd overkill, but it was a good excuse to learn something about the Google API.

If you have this problem too you can download my application here:

http://scrappydog.com/GoogleGroupCleanup/publish.htm

Note: This is a very simple brute force application. It will delete ALL your email groups (no way to keep the 10 you REALLY care about).

You can read more about the issue here on their support site:

http://getsatisfaction.com/soocial/topics/synchronization_creates_duplicate_groups

UPDATE: Soocial is currently offline. I get prompted for a password when I try to access their site... I would guess the are busy fixing bugs... :-)

UPDATE2: This tool still gets a surprising number of downloads, and today "Ben" asked if I would share the source code. No problem. Here is the link: http://blog.scrappydog.com/2010/02/souce-code-for-deleting-googlegmail.html

Friday, January 16, 2009

"Failed to copy file" Error when publishing VS2008 application via FTP

I need to share a little .NET console application with a couple random people, and instead of emailing it I thought I would publish it to my web server as a "Click Once" application.

Simple right? Wrong! I'm trying to publish via FTP and getting the following error:

Failed to copy file 'C:\Projects\scrappydog_projects\Google\libgoogle-data-mono-1.3.1.0\src\GoogleGroupCleanup\bin\Debug\app.publish\Application Files\GoogleGroupCleanup_1_0_0_0\Google.GData.Client.dll.deploy' to 'ftp://scrappydog.com/GoogleGroupCleanup/Application Files/GoogleGroupCleanup_1_0_0_0/Google.GData.Client.dll.deploy'. Unable to add 'Application Files/GoogleGroupCleanup_1_0_0_0/Google.GData.Client.dll.deploy' to the Web site. Could not find a Web server at 'scrappydog.com' on port 21. Please check to make sure that the Web server name is valid and your proxy settings are set correctly. If you are sure that everything is correct, the Web server may be temporarily out of service.

I can watch the files being created on the server with a ftp client, and so I know it's connecting, but somewhere at the end of the process something else fails, and rolls back the whole process and deletes the files... aargh...

I've found lots of references to the same problem, but no solutions... anyone? anyone?

UPDATE: This issue seems like it may be firewall related. Publishing the same project from a different computer on a different network works fine...