tag:blogger.com,1999:blog-5943923481855331372024-03-14T06:47:44.769-05:00ScrappyDogOn the Internet nobody knows you're a dogEric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.comBlogger59125tag:blogger.com,1999:blog-594392348185533137.post-78873926044796938262012-06-04T12:17:00.000-05:002012-06-04T12:37:50.788-05:00Updating ScrappyDB Membership Provider to support Amazon DynamoDBFor anyone that is interested in using the ScrappyDB ASP.NET Membership Provider for Amazon SimpleDB...<br />
<br />
I would like to announce that I am actively developing an updated version of ScrappyDB that will also support Amazon DynamoDB as a backend. Functionality should be identical, and it should be transparent which backend you are using.<br />
<br />
The primary differences are pricing and scalability:<br />
<ul>
<li>For a low volume site SimpleDB should be cheaper.</li>
<li>For a high volume site DynamoDB should provide near infinite scalability with consistent performance.</li>
</ul>
<div>
Expected release date: "real soon now"</div>Anonymoushttp://www.blogger.com/profile/12214494033421947840noreply@blogger.com1tag:blogger.com,1999:blog-594392348185533137.post-32237080542246438862011-08-19T10:27:00.000-05:002011-08-19T11:00:41.173-05:00Speaking at MDC in SeptemberI'll be speaking at the Minnesota Developers Conference on September 29th (<a href="http://mdc.ilmservice.com/">http://mdc.ilmservice.com</a>). <br />
<br />
Topic: "An ALT.NET Microsoft cloud: Developing and hosting ASP.NET MVC apps in the cloud without Azure. Demonstration and discussion of alternate tools and platforms for developing cloud based .NET applications including: Managing dependencies with Nuget. Source code control with Mercurial and Bitbucket. Continuous Integration and hosting with AppHarbor and Amazon EC2. NoSQL database backends with Amazon Simple DB."Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-91657552539517758902011-06-27T15:28:00.003-05:002011-06-27T15:42:42.845-05:00ScrappyDB: Code First + Linq for Amazon SimpleDBFor several years I've been working on ScrappyDB, which is my personal open source .NET library for Amazon SimpleDB.<br /><br />I quietly released version 1.0 on CodePlex (<a href="http://scrappydb.codeplex.com/">http://scrappydb.codeplex.com/</a>) several years ago, and despite a few downloads I'm not aware of a single production user (other than me). Not to worry... no hard feelings... I wrote this for my own use and released it in hopes that it "might" prove useful for somebody else someday...<br /><br />This month I released version 2.0 to Nuget (<a href="http://nuget.org/List/Packages/ScrappyDB">http://nuget.org/List/Packages/ScrappyDB</a>) with slightly higher expectations: <i> "ScrappyDB 2.0 is a code first style object mapping library and Linq provider for Amazon SimpleDB. Also included is an ASP.NET Membership Provider for Amazon SimpleDB."</i><br /><br />With support for "Entity Framework style" code first syntax and Linq I'm hopeful that a few other people might actually find this useful. But nobody is going to use it if they can't find it and so I'm taking it upon myself to start writing a few blog posts demonstrating how it works, and eventually to highlight how easy it is to use Amazon SimpleDB as a backend for .NET websites.<br /><br />To get started here are a few code examples that demonstrate using ScrappyDB to run the example queries found in the excellent SimpleDB <a href="http://aws.amazon.com/articles/1231">Query 101</a> document from Amazon:<br /><br />Following EF Code First conventions we create a class to define our schema and then a context class to access the database. The only syntactic difference between EF and ScrappyDB at this point is "SdbContext" in place of "DbContext".<br /><pre class="brush: csharp;"> <br />public class AwsSampleContext : SdbContext<br /> {<br /> public SdbSet<book> Books { get; set; }<br /> }<br /><br />public class Book<br /> {<br /> public string Id { get; set; }<br /> public string Title { get; set; }<br /> public string Author { get; set; }<br /> public string Year { get; set; }<br /> public int YearInt { get; set; }<br /> public int NumberOfPages { get; set; }<br /> public List<string> Keywords { get; set; }<br /> public List<string> Rating { get; set; }<br /> }<br /></string></string></book></pre><br />To execute the sample query:<br /><pre class="brush: sql;">select * from mydomain where Title = 'The Right Stuff'</pre>All we would need to do is:<br /><pre class="brush: csharp;">var dbContext = new AwsSampleContext();<br />var result = from a in dbContext.Books where a.Title == "The Right Stuff" select a;</pre>SimpleDB only supports one datatype which is a string. This means no native numeric types, no datetime. ScrappyDB supports strongly typed data for a subset of common .NET types.<br /><br />Linq was designed generically and doesn't always map well to underlying database features and implementation oddities. This is particularly true with SimpleDB, where the "simple" feature set can't support many concepts that are typical in Linq to SQL.<br /><br />Here is another sample query from the Query 101 document, and several different ways to approach implmenting it in ScrappyDB:<br /><pre class="brush: sql;">select * from mydomain where Year > '1985'</pre>The .NET centric way to implement this in ScrappyDB would be to define the Year field as a numeric type, in which case the Linq query would be as you might expect from Linq to SQL:<br /><pre class="brush: csharp;">var dbContext = new AwsSampleContext();<br />var result = from a in dbContext.Books where a.YearInt > 1985 select a;</pre>If you defined the field "Year" as a string in your .NET class then you will need to use the ScrappyDB specific extension method "GreaterThan" to implement this query:<br /><pre class="brush: csharp;">var dbContext = new AwsSampleContext();<br />var result = from a in dbContext.Books where a.Year.GreaterThan("1985") select a;</pre>If you would like to see more you can check out the source code on BitBucket (<a href="https://bitbucket.org/scrappydog/scrappydb">https://bitbucket.org/scrappydog/scrappydb</a>). The Integration Tests in the source implement almost all the examples from the Query 101 document.<br /><br />To see ScrappyDB in a Sample MVC 3 application check out the sample code on BitBucket (<a href="https://bitbucket.org/scrappydog/scrappydb.mvcsample">https://bitbucket.org/scrappydog/scrappydb.mvcsample</a>) or check out the sample application running on <a href="http://http//appharbor.com/">AppHarbor</a> (<a href="http://sample.scrappydb.com/">http://sample.scrappydb.com/</a>).<br /><br />Note: AppHarbor runs on Amazon EC2, and so it is a GREAT place to host applications that use SimpleDB as a backend!<br /><br />The easiest way to try ScrappyDB for yourself is to add it into your Visual Studio project with Nuget (<a href="http://nuget.org/List/Packages/ScrappyDB">http://nuget.org/List/Packages/ScrappyDB</a>).Anonymoushttp://www.blogger.com/profile/12214494033421947840noreply@blogger.com1tag:blogger.com,1999:blog-594392348185533137.post-37718682452625529062010-09-22T11:27:00.001-05:002010-09-22T11:28:38.509-05:00Great tip on serving compressed CSS and Java Script files from Amazon S3Fantastic performance tip on hosting compressed CSS and javascipt file from Amazon S3:<br />
<br />
<i>"Typically, I use a tool called Juicer ( <a href="http://github.com/cjohansen/juicer">http://github.com/cjohansen/juicer</a>) to concatenate and compress my CSS and JavaScript files (with YUI Compressor and Google Closure Compiler, respectively) to ensure they're as small as possible and require the fewest number of HTTP requests ( <a href="http://developer.yahoo.com/performance/rules.html#num_http">http://developer.yahoo.com/performance/rules.html#num_http</a>). <br />
<br />
After that, I launch Terminal and run `gzip -9 filename.css && gzip -9 filename.js` to compress them as tightly as possible. This will give me filename.css.gz and filename.js.gz. I remove the .gz extension, and upload those files to S3. <br />
<br />
Lastly, I add a custom HTTP header — `Content-Encoding: gzip` — to each of the files in S3. This tells the browser the same thing as Apache would if it were compressing them on the fly. The browser then knows to decompress the content after downloading it. <br />
<br />
Since the files are pre-compressed instead of compressing on the fly (a la Apache), fewer server resources are used and the response times are faster. "<br />
</i><br />
<br />
<br />
Original source: <a href="http://developer.amazonwebservices.com/connect/thread.jspa?messageID=194918&tstart=0#194918">http://developer.amazonwebservices.com/connect/thread.jspa?messageID=194918&tstart=0#194918</a>Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-44787493910872434912010-09-14T11:20:00.002-05:002010-09-14T11:22:15.512-05:00Last day on the 3M VAS project<div class="separator" style="clear: both; text-align: center;"><a href="http://vas.3m.com" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://3mvas.blob.core.windows.net/vascontent/VideoHP.jpg" /></a></div>Today marks my last official day on the 3M VAS project (<a href="http://vas.3m.com/">http://vas.3m.com</a>). It's been fun getting to develop a production site for a major company with Silverlight 4 and Azure!<br />
<br />
Mike Hodnick, one of my colleagues on the development team has a nice wrap up post about the project on his blog: <a href="http://hodnick.com/post/1121185443/vas3m">http://hodnick.com/post/1121185443/vas3m</a><br />
<br />
(Just to be clear: 3M VAS is very much alive and well. This is just the end of a major release cycle and most of the development team is moving on to other projects.)Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-70016560184284944742010-09-07T15:34:00.001-05:002010-09-08T09:09:38.629-05:00Moving to Google Voice as my primary public phone number<div class="separator" style="clear: both; text-align: center;"><a href="https://www.google.com/voice" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://www.google.com/voice/resources/688809805-voice_logo_sm.gif" /></a></div>I've been playing around with Google Voice for a while know and I really like the speech to text transcription it does on voicemails, and so I've decided to start using it as my primary phone number for all business stuff.<br />
<br />
Interesting to note how much Google and Amazon cloud stuff I use in my day to day life... and nothing from Microsoft... hmmm...Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-74143214362201537132010-08-13T09:37:00.000-05:002010-08-13T09:37:36.988-05:00Desktop performance tweaking: using an SSD for ReadyBoost and Virtual Memory Paging FileLittle known fact: Windows 7 CAN use an internal SSD drive for ReadyBoost.<br />
<br />
Example scenario where it makes "some" sense: You have an existing Windows 7 desktop that could use a performance boost, but you don't have time to reinstall/migrate the boot drive to an SSD.<br />
<br />
* Install a cheap SSD, and configure it for ReadyBoost (just right click on the drive the same as you would a USB Flash drive). NOTE: ReadyBoost will only use 4GB of the drive.<br />
<br />
* Move your virtual memory paging file from the boot drive to the SSD.<br />
<br />
* Move any data files you are working with actively to the SSD (such as source code if you are developer).<br />
<br />
Total time to implement: About 10 minutes<br />
Performance improvement: Noticeable/useful but not magicalEric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com1tag:blogger.com,1999:blog-594392348185533137.post-29093779852588999972010-07-07T18:03:00.002-05:002010-07-07T18:05:36.008-05:00BUG: VS2010 outsmarts itself and auto "fixes" references and breaks the build server!<b>Classic Problem:</b> .NET project builds fine on local developers workstation but fails on the build server because the developer referenced DLL's that were in the GAC on their workstation but don't exist on the build server.<br />
<br />
<b>Classic (POOR) Solution #1:</b> Install the files on the build server and add them to GAC. This "works" but it's a maintenance hassle and the build master may not want you to install obscure tool FooBar.dll on "his" build server.<br />
<br />
<b>Classic (BETTER) Solution #2:</b> Create a lib directory (or whatever your local naming custom happens to be) in your source tree, copy FooBar.dll into the lib directory and change all of your references to point to the files in the lib folder instead of the GAC. Now the build server will get the dll's it needs from source control and your project should build happily. Problem Solved!<br />
<br />
<b>Insidious new VS2010 BUG (probably a "feature"):</b> You try and solve the problem using Class Solution #2 above. You create a lib directory, you copy dll's into it, you delete the problem references, you recreate the problem references, you checkin your changes, and YOUR BUILD IS STILL BROKEN! WTF?<br />
<br />
It turns out the Visual Studio 2010 believes it is smarter than you are! When you added your new reference by browsing to the dll, Visual Studio looked at the file and said "Ah ha!" is see the exact same dll in the GAC and I'll add the reference as a GAC reference instead because this stupid developer obviously doesn't understand the power and beauty that is the GAC!<br />
<br />
Being an experienced .NET developer after several failed builds you smell a rat, and open the project file in notepad and see the following:<br />
<br />
<pre class="brush: xml;"><itemgroup>
<... stuff deleted for clarity ... />
<reference Include="System.Windows.Controls.Data.DataForm.Toolkit, Version=4.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<reference Include="System.Windows.Controls.Toolkit, Version=4.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<... stuff deleted for clarity ... />
</ItemGroup>
</pre><br />
Now that dog don't hunt because System.Windows.Controls.Data.DataForm.Toolkit.dll and System.Windows.Controls.Toolkit.dll don't exist in the GAC on the build server.<br />
<br />
You are SURE you changed both of those references to files references, and so you delete them and re-add them as file references again just to be sure. Same screwed up result...<br />
<br />
And so now in frustration you manually edit the project file(s) like this (below) to create the file references that Visual Studio 2010 wouldn't let you create through the UI.<br />
<br />
<pre class="brush: xml;"><itemgroup>
<... stuff deleted for clarity ... />
<reference Include="System.Windows.Controls.Data.DataForm.Toolkit" >
<hintpath>..\lib\System.Windows.Controls.Data.DataForm.Toolkit.dll</HintPath>
</Reference>
<reference Include="System.Windows.Controls.Toolkit" >
<hintpath>..\lib\System.Windows.Controls.Toolkit.dll</HintPath>
</Reference>
<... stuff deleted for clarity ... />
</ItemGroup>
</pre><br />
Success! Your solution builds on the build server! <br />
<br />
And you are reminded yet again that GAC is evil...Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com1tag:blogger.com,1999:blog-594392348185533137.post-30170517159616132742010-07-05T14:28:00.004-05:002010-07-05T14:53:25.939-05:00Repo: fullscreen bug in Silverlight 4 crashes browser in 4 mouse clicksThis app is a demonstration of a bug in Silverlight 4 that will crash your browser in about 4 mouse clicks.<br />
<br />
Instructions: Click the "Full Screen Toogle" button and close the resulting messagebox a few times and then... poof! (you might want to bookmark the page first :-)<br />
<br />
<br />
<div id="silverlightControlHost"><object data="data:application/x-silverlight-2," height="100%" type="application/x-silverlight-2" width="100%"> <param name="onError" value="onSilverlightError" /><param name="background" value="white" /><param name="minRuntimeVersion" value="4.0.50401.0" /><param name="autoUpgrade" value="true" /><a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50401.0" style="text-decoration:none"> <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/> </a> </object><iframe id="_sl_historyFrame" style="border: 0px none; height: 0px; visibility: hidden; width: 0px;"></iframe></div><br />
<script type="text/javascript">
var host = "http://www.figmentengine.com/";
var source = "http://scrappydog.com/ClientBin/Silverlight.Fullscreen.Bug.xap";
var parentElement = document.getElementById("silverlightControlHost");
var callbackId = "silverlightControlHost2";
var properties = { width: "400", height: "300", version: "4.0.50401.0"};
var events = {}; Silverlight.createObject(source, parentElement, callbackId, properties, events);
</script><br />
<br />
Here is the code to reproduce the bug:<br />
<br />
<br />
<pre class="brush: xml;"><usercontrol d:designheight="300" d:designwidth="400" mc:ignorable="d" x:class="Silverlight.Fullscreen.Bug.MainPage" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<grid background="Black" x:name="LayoutRoot">
<button canvas.zindex="10" click="button1_Click" content="Full Screen Toggle" height="30" horizontalalignment="Center" name="button1" verticalalignment="Center" width="200">
<img canvas.zindex="-1" horizontalalignment="Left" name="image1" source="/Resources/Chrysanthemum.jpg" stretch="Fill" verticalalignment="Top" />
</button></grid>
</usercontrol>
</pre><br />
<pre class="brush: csharp;">using System.Windows;
using System.Windows.Controls;
namespace Silverlight.Fullscreen.Bug
{
public partial class MainPage : UserControl
{
private bool firstClick = true;
public MainPage()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
if (firstClick)
{
//this firstclick logic is just a convienence so that you don't get a message box the first time the page opens
//it is NOT need to reproduce the bug...
image1.SizeChanged += Image_SizeChanged;
firstClick = false;
}
Application.Current.Host.Content.IsFullScreen = !Application.Current.Host.Content.IsFullScreen;
}
private void Image_SizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
{
MessageBox.Show("Image_SizeChanged");
}
}
}
</pre><br />
<b><span style="color: red;">UPDATE: </span></b>This bug appears to be Windows specific. I can't reproduce it on a Mac...Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-45457363376737585842010-06-09T13:35:00.003-05:002010-06-09T13:51:05.702-05:00What I'm working on: Image Analysis at 3MI'm working on an interesting project at 3M. The Visual Attention Service (<a href="https://vas.3m.com/">https://vas.3m.com/</a>) is an online service that will analyze an image and tell you what parts of the image a viewer is most likely to look at in the first few seconds.<br />
<br />
A very useful thing in designing advertising... what will users notice first? The surgeon generals warning or the 10% off coupon?<br />
<br />
So here's a real world example of the tool in action:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmw3_ymWsho0YSaePyHDNNqftOw30SILjbiKqsRqAoWZe2b4XRcTjCYB36uDWgtZTbY65WZgneCltO9TbZ3iQ7SZ5P8UrID8iExC169-rfXcvcmVB4oStUAmssz4yG3fz45sC-xY1ftIiP/s1600/every+time+you+break+a+build.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmw3_ymWsho0YSaePyHDNNqftOw30SILjbiKqsRqAoWZe2b4XRcTjCYB36uDWgtZTbY65WZgneCltO9TbZ3iQ7SZ5P8UrID8iExC169-rfXcvcmVB4oStUAmssz4yG3fz45sC-xY1ftIiP/s640/every+time+you+break+a+build.jpg" width="640" /></a></div><br />
If you are not familiar with this image it's a classic bit of software developer humor about compiling and testing code.<br />
<br />
It turns out that the tool believes that most people will notice the scary monsters first NOT the kittens (as shown by the heat map below)...<br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZkjnl-b5gAOMgUsA2pzMQy_pj8PnnINCl4Q0BGySzj9x0InE6QHpXG0EsiQui13DTGAqil3YA_Yu8x2FdAHVr3je0JYLaC-MTkQ_-ZgZE1_WLapmylZvIeYYpEGR-DZtct6rhEC6oWPXh/s1600/9055_ahs_708f08e7-d2cc-4657-b76e-901ae6836085.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZkjnl-b5gAOMgUsA2pzMQy_pj8PnnINCl4Q0BGySzj9x0InE6QHpXG0EsiQui13DTGAqil3YA_Yu8x2FdAHVr3je0JYLaC-MTkQ_-ZgZE1_WLapmylZvIeYYpEGR-DZtct6rhEC6oWPXh/s640/9055_ahs_708f08e7-d2cc-4657-b76e-901ae6836085.jpg" width="640" /></a></div><br />
DISCLAIMER: No kittens where actually harmed in the creation of this blog post.Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-67579747588490459422010-05-24T12:33:00.001-05:002010-05-24T12:34:26.673-05:00Customer support issue: Installing Silverlight on the Mac<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ab0yDYOi1qqAvPXaUFlDnXlQCE09MLqbxKrtuu0pg_rPX3MYIhMw6h6HJ6xQSt_LDgKb6rOxtWW0XVBevSKF6jBdmQNuG0PXhmhKZJqnXIKy1yeoVU5W7bsn-JqqhaKYzdpiSgm6IcXd/s1600/pmg5-160.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ab0yDYOi1qqAvPXaUFlDnXlQCE09MLqbxKrtuu0pg_rPX3MYIhMw6h6HJ6xQSt_LDgKb6rOxtWW0XVBevSKF6jBdmQNuG0PXhmhKZJqnXIKy1yeoVU5W7bsn-JqqhaKYzdpiSgm6IcXd/s320/pmg5-160.jpg" /></a></div>I was just dealing with an escalated end-user problem with a production Silverlight application here at *nameless* Fortune 500:<br />
<br />
User: I can't get your Silverlight app to install on my "new" Mac.<br />
<br />
Support: What browser and OS version are you running.<br />
<br />
User: I'm using Safari on a <b>G5 tower</b> running OSX 10 something.<br />
<br />
Me: Um... The G5 is a PowerPC based computer. Apple announced their retirement in 2005, hasn't sold them since early 2006, and the current version of OSX doesn't install on them... And no, Silverlight doesn't run on them either...<br />
<br />
Sorry...Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-67641021328807883412010-05-19T11:56:00.000-05:002010-05-19T11:56:16.582-05:00Solved: RIA Services work on development server but fail on IISI'm building a prototype Silverlight 4 application using the Silverlight Business Application template as a starting point (I chose this template so that I could get ASP.NET forms authentication working "quickly").<br />
<br />
My test app worked fine in the development web server (aka Casini if you are old enough to remember that), but it didn't work in IIS.<br />
<br />
After some digging I found this post: <a href="http://blogs.msdn.com/saurabh/archive/2010/03/16/ria-services-application-deployment.aspx">Deploying Application built using RIA Services RC</a> which solved my problem. Solution: disable basic and integrated (aka: NT) auth.<br />
<br />
Details from Saurabh's post: <i>"WCF (and by association RIA Services) has a limitation that it <strong>does not support MultipleAuthenticationSchemas enabled </strong>in IIS. So if you are using Forms Authentication in your application (if you built your application using the Business Application template, Forms Auth is the default there) you need to make sure that for the IIS VirtualRoot that hosts your WebApp Forms Auth is enabled. Forms Auth + Anonymous will also work fine but Forms Auth + Integrated Auth is not supported."</i>Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-19527523929360651962010-03-31T14:43:00.002-05:002010-03-31T14:46:41.402-05:00The iPad and the future of "computers"<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://images.apple.com/in/hotnews/images/featured/ipadavailableinusonapril3201003080908.jpg"><img style="float: right; margin: 0pt 0pt 10px 10px; cursor: pointer; width: 140px; height: 100px;" src="http://images.apple.com/in/hotnews/images/featured/ipadavailableinusonapril3201003080908.jpg" alt="" border="0" /></a><br />Eric Sink has a great post today discussing the future of computers:<br /><br /><a href="http://www.ericsink.com/entries/dual_class_computing.html">http://www.ericsink.com/entries/dual_class_computing.html</a><br /><br />The key points that caught my attention (paraphrased and reinterpreted by me):<br /><ol><li>The iPhone and iPad represent a shift in the "computer" market towards simpler devices for consumers that do what they want and they can't screw up. These devices will start to meet the computing needs of most users. No need for a "real" computer, and no need to call your geeky relative to come fix it regularly.</li><li>"Computers" as we know them today with numerous options and a high degree of complexity will become a niche product for a relatively small number of users with specialized needs.</li><li>Microsoft is set to miss this seismic shift in the computer landscape.</li></ol>Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-31976379340253198882010-02-02T19:13:00.005-06:002010-02-02T19:26:35.502-06:00Souce code for deleting Google/Gmail Contact GroupsOver a year ago I posted a little utility for deleting unwanted groups out of your Gmail Contacts.<br /><br />Blog post here: <a href="http://blog.scrappydog.com/2009/01/deleting-4000-gmail-groups-or-repairing.html">http://blog.scrappydog.com/2009/01/deleting-4000-gmail-groups-or-repairing.html</a><br /><br />Application install here: <a href="http://scrappydog.com/GoogleGroupCleanup/publish.htm">http://scrappydog.com/GoogleGroupCleanup/publish.htm</a><br /><br />I wrote this for my own use because a bad replication tool had created 10,000+ bogus groups in my Contacts, and I REALLY didn't want to delete them by hand!<br /><br />Apparently, it has saved a fair number of other people's <a href="http://whatever.scalzi.com/2006/09/13/clearly-you-people-thought-i-was-kidding/">bacon</a> as well...<br /><br />Today "Ben" asked if I could post the source code for my tool? And so here it is (not much to it):<br /><br /><pre class="brush: csharp;"><br />using System;<br />using Google.GData.Contacts;<br /><br />namespace GoogleGroupCleanup<br />{<br /> class Program<br /> {<br /> static void Main(string[] args)<br /> {<br /> try<br /> {<br /> Console.WriteLine("Google Gmail Group Cleanup Tool");<br /> Console.WriteLine();<br /> Console.WriteLine("Written by: Eric Bowen (googlegroupcleanup@scrappydog.com)");<br /> Console.WriteLine();<br /> Console.WriteLine("This application is provided WITHOUT any guarantee. Use at your own risk.");<br /> Console.WriteLine();<br /> Console.WriteLine("This application will delete ALL groups from your Gmail account.");<br /> Console.WriteLine("It will NOT delete any of your contacts or email.");<br /> Console.WriteLine();<br /> Console.WriteLine(<br /> "This application deletes up to 1,000 groups at a time. If you have more than 1,000 groups to delete you will need to run it multiple times.");<br /><br /><br /> Console.WriteLine();<br /> Console.Write("Enter Google email address (this will not be stored): ");<br /> string email = Console.ReadLine();<br /><br /> Console.WriteLine();<br /> Console.Write("Enter Google password (this will not be stored): ");<br /> string password = Console.ReadLine();<br /><br /> var service = new ContactsService("gmail-group-cleanup");<br /> service.setUserCredentials(email, password);<br /><br /> var groupQuery = new GroupsQuery(GroupsQuery.CreateGroupsUri("default"));<br /> groupQuery.NumberToRetrieve = 1000;<br /> var groupsFeed = service.Query(groupQuery);<br /><br /> int counter = 0;<br /> foreach (GroupEntry group in groupsFeed.Entries)<br /> {<br /> Console.WriteLine(group.Content.Content);<br /> group.Delete();<br /> counter++;<br /> }<br /><br /> Console.WriteLine();<br /> Console.WriteLine(counter.ToString() + " groups deleted");<br /> Console.WriteLine();<br /> }<br /> catch (Exception ex)<br /> {<br /> Console.WriteLine("Exception:");<br /> Console.WriteLine(ex.Message);<br /> Console.WriteLine();<br /> }<br /> Console.WriteLine("Press any key to exit");<br /> Console.ReadKey();<br /> }<br /> }<br />}<br /></pre>Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com8tag:blogger.com,1999:blog-594392348185533137.post-22867226250293514892009-12-04T16:01:00.002-06:002009-12-04T16:02:33.330-06:00SetPropertyValues never called in custom ProfileProviderI'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...<br /><br />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.<br /><br />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.<br /><br />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.<br /><br />After hours of trashing about I finally found the answer in this thread: <a href="http://forums.asp.net/t/635411.aspx">http://forums.asp.net/t/635411.aspx</a><br /><br />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.<br /><br />Here is the quote from the thread that finally solved the problems for me:<br /><br /><i>"Basically, somewhere in GetPropertyValues, there should be code new'ing up SettingsPropertyValue instances that looks like: </i><br /><br /><i>SettingsPropertyValue sv = new SettingsPropertyValues(SettingsPropertyInstanceGoesHere); </i><br /><br /><i>You get the SettingsProperty instance from the SettingsPropertyCollection that is passed in as a parameter to the GetPropertyValues method."</i><br /><br />When I'm done these providers will be published on Codeplex as part of my <a href="http://scrappydb.codeplex.com/">ScrappyDB C# library for SimpleDB</a>.<i><br /></i>Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-56937442514685440722009-11-29T15:50:00.002-06:002009-11-29T15:55:45.654-06:00Happy Holidays!<div style="padding: 3px; text-align: left;"><a href="http://www.flickr.com/photos/ericbowen/4141640491/" title="photo sharing"><img src="http://farm3.static.flickr.com/2672/4141640491_c7465cdb67.jpg" style="border: 2px solid rgb(0, 0, 0);" alt="" /></a><br /><span style="margin-top: 0px;font-size:0.8em;" ><a href="http://www.flickr.com/photos/ericbowen/4141640491/"></a>, originally uploaded by <a href="http://www.flickr.com/people/ericbowen/">ScrappyDog</a>.</span></div><p>Family 2.0 portrait at "the Farm" in Grand Marais over Thanksgiving. Photo by Gramma Betsy.<br /></p>Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-43654648919570389762009-11-11T11:44:00.001-06:002009-11-11T14:25:24.535-06:00Question from a friend: I need a more "professional" email address, but I don't want to give up my Gmail addressQuestion 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.<br /><br />Example current address: binge.drinker@gmail.com<br />New email address: john.a.doe@gmail.com<br /><br />No problem!<br /><ol><li>First step create the new Gmail account. </li><li>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).</li><li>Go into the new email box and click on the "Settings" link at the top right.</li><li>Select the "Forwarding and POP/IMAP" tab.<span> </span></li><li><span>Select "</span>Forward a copy of incoming mail to" and enter the email address of the old account.</li><li>I would recommend setting "archive Gmail's copy".<br /></li></ol><span><br />You are now done with step one. All email sent to the new address should start showing up in you old inbox.</span><span> Now you want to be able choose which address to use when you send/reply to email in your old inbox.</span><span> </span><ol><li><span>G</span>o into the old email box and click on the "Settings" link at the top right.</li><li>Select the "Accounts and Import" tab.</li><li>Go to the "Send mail as:" section and click the "Send mail from another address" button enter the other (new) email address.<span class="rc"> </span></li><li><span class="rc">Check the "</span>Reply from the same address the message was sent to" option.</li><li>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.<br /></li></ol><span> You should be all set. <br /><br />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.</span>Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-76934859318173161702009-11-09T20:09:00.002-06:002009-11-09T20:19:06.695-06:00ScrappyDB: C# Object Mapper for Amazon SimpleDBI'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.<br /><br /><a href="http://scrappydb.codeplex.com/">http://scrappydb.codeplex.com/</a><br /><br /><b>Project Description</b><br /><br />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...<br /><br /><b>Why create an new tool instead of using one of the existing .NET tools for SimpleDB? </b><br /><br />In particular: <ul><li>Simple Savant <a href="http://simplesavant.codeplex.com/" class="externalLink">http://simplesavant.codeplex.com/<span class="externalLinkIcon"></span></a> (Simple Savant is a great tool and definitly a more mature code base. We would recommend that you investigate it first before considering ScrappyDB.)</li></ul><br /><b>Features that we felt were important for our implementation:</b> <ul><li>Support for multi-value attributes (using arrays or arraylists).</li><li>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).</li><li>Integrated support for web caching for performance.</li><li>Location data (in particular the ability to do proximity searches "show me all records within 5 miles of X").</li></ul><br /><b>Things that we did <u>NOT</u> feel were important for our implementation:</b> <ul><li>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).</li><li>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).</li></ul><br /><b>About the source code</b> <ul><li>To do what it does ScrappyDB makes extensive use of some painful reflection. </li><li>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..."</li></ul><br /><b>Known Issues:</b> <ul><li>Current code is definitely ALPHA, has not had any significant production use.</li><li>Relationship logic is lightly testing, is probably buggy and is likely to see some significant refactoring. <ul><li>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).</li></ul></li></ul><br /><b>Dependencies</b> <ul><li>ScrappyDb is dependent on the excellent Amazon C# Library for SimpleDB <a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1133&categoryID=148" class="externalLink">http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1133&categoryID=148<span class="externalLinkIcon"></span></a></li></ul><br /><b>Documentation</b> <ul><li>Currently the primary developer documentation for ScrappyDB is the unit tests included with the source code.<br /></li></ul><br />But here are a few basic examples to help you get started:<br /><div id="WikiContent" class="WikiContent"><div class="wikidoc"><br /><br /><b>Basic Save</b><br /><div style="color: Black; background-color: White;"><pre> <span style="color: Blue;">var</span> db = <span style="color: Blue;">new</span> DB();<br /> <span style="color: Blue;">var</span> o = <span style="color: Blue;">new</span> MyClass {Id = Guid.NewGuid, TestProperty = <span style="color: rgb(163, 21, 21);">"HelloWorld"</span>};<br /> db.Save(o);<br /></pre></div><br /><b>Basic Load by Id</b><br /><div style="color: Black; background-color: White;"><pre> <span style="color: Blue;">var</span> result = db.Load<myclass>(testId);<br /></pre></div><br /><b>Save a Collection</b><br /><div style="color: Black; background-color: White;"><pre> <span style="color: Blue;">var</span> a = <span style="color: Blue;">new</span> ScrappyDbCollection<testitem>();<br /> a.Add(<span style="color: Blue;">new</span> TestItem() { Id = Guid.NewGuid(), TestString = <span style="color: rgb(163, 21, 21);">"test1"</span> });<br /> a.Add(<span style="color: Blue;">new</span> TestItem() { Id = Guid.NewGuid(), TestString = <span style="color: rgb(163, 21, 21);">"test2"</span> });<br /> a.Add(<span style="color: Blue;">new</span> TestItem() { Id = Guid.NewGuid(), TestString = <span style="color: rgb(163, 21, 21);">"test3"</span> });<br /><br /> a.Save();<br /></pre></div><br /><b>Query a Collection</b><br /><div style="color: Black; background-color: White;"><pre> <span style="color: Blue;">var</span> b = <span style="color: Blue;">new</span> ScrappyDbCollection<testitem>();<br /> b.QueryCollection(<span style="color: rgb(163, 21, 21);">" TestString = 'test2' "</span>);<br /></pre></div></div> </div> <span class="SubText"> </span>Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-59015866340966047432009-09-01T14:52:00.003-05:002009-09-02T05:21:11.532-05:00WSOD Google Style (White Screen of Darn)<style><!--body {font-family: arial,sans-serif}div.nav {margin-top: 1ex}div.nav A {font-size: 10pt; font-family: arial,sans-serif}span.nav {font-size: 10pt; font-family: arial,sans-serif; font-weight: bold}div.nav A,span.big {font-size: 12pt; color: #0000cc}div.nav A {font-size: 10pt; color: black}A.l:link {color: #6f6f6f}A.u:link {color: green}//--></style>My Google Apps email server is down at the moment, so I thought I would share the error message... Why? "Because it was there."<br /><br />FYI: There is an application status page at Google for major apps: <a href="http://www.google.com/appsstatus">http://www.google.com/appsstatus</a><br /><br />UPDATE: Great post on the Gmail Blog detailing what caused today's outage: <a href="http://gmailblog.blogspot.com/2009/09/more-on-todays-gmail-issue.html">http://gmailblog.blogspot.com/2009/09/more-on-todays-gmail-issue.html</a><br /><br /><table border="0" cellpadding="2" cellspacing="0"><tbody><tr><td rowspan="3" width="1%" nowrap="nowrap"><br /><span style="font-size:180%;"><b><span style="color: rgb(0, 57, 182);font-family:times;" >G</span><span style="color: rgb(196, 18, 0);font-family:times;" >o</span><span style="color: rgb(243, 197, 24);font-family:times;" >o</span><span style="color: rgb(0, 57, 182);font-family:times;" >g</span><span style="color: rgb(48, 167, 47);font-family:times;" >l</span><span style="color: rgb(196, 18, 0);font-family:times;" >e</span> </b></span><br /></td><td><br /></td></tr><tr><td bgcolor="#3366cc"><b>Error</b></td></tr><tr><td><br /></td></tr></tbody></table><blockquote><h1>Server Error</h1>The server encountered a temporary error and could not complete your request.<br />Please try again in 30 seconds.<br /><br /></blockquote><table cellpadding="0" cellspacing="0"><tbody><tr><td bgcolor="#3366cc"><img src="http://www.blogger.com/post-edit.do" alt="" width="1" height="4" /></td></tr></tbody></table>Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-19438838378069172602009-06-18T10:30:00.001-05:002009-06-18T10:30:00.651-05:00Happy Early Father's Day To Me!<div style="text-align: left; padding: 3px;"><a href="http://www.flickr.com/photos/ericbowen/3638117021/" title="photo sharing"><img src="http://farm4.static.flickr.com/3588/3638117021_d929d89607.jpg" style="border: solid 2px #000000;" alt="" /></a><br /><span style="font-size: 0.8em; margin-top: 0px;"><a href="http://www.flickr.com/photos/ericbowen/3638117021/">300_9227</a>, originally uploaded by <a href="http://www.flickr.com/people/ericbowen/">ScrappyDog</a>.</span></div><p>The kids all got matching shirts (including one for me) for a Father's Day picture...</p>Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-33923336539920518582009-06-11T09:13:00.001-05:002009-06-11T09:13:03.636-05:00MVVM Questions: Can a View Model close a window and other puzzlers<p>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?</p> <p>Questions:</p> <ol> <li>Does a Window create it’s View Model? </li> <li>Or does the View Model create it’s Window? </li> <li>Or does “something else” create the View Model and the Window and then bind them together? </li> <li>How do you close a Window?  </li> <li>Can a View Model close itself and it’s Window? </li> </ol> <p>Our Answers:</p> <ol> <li>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 . </li> <li>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. </li> <li>If a user (or something else) tries to close a Window we catch the Window_Closing event  using <a href="http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/">AttachedCommandBehavior</a> (see XAML below) and call a command on the View Model Base Class to give the View Model control over the closing event. <pre class="brush: xml;"><acb:CommandBehaviorCollection.Behaviors><br /> <acb:BehaviorBinding Event="Initialized" Command="{Binding Path=Window_InitializedCommand}" /><br /> <acb:BehaviorBinding Event="Activated" Command="{Binding Path=Window_ActivatedCommand}" /><br /> <acb:BehaviorBinding Event="Closing" Command="{Binding Path=Window_ClosingCommand}" /><br /></acb:CommandBehaviorCollection.Behaviors></pre><br /> </li><br /><br /> <li>View Models have the ability to close themselves (and their related Window) by calling the Window Service. </li><br /></ol> Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-65414993029904633852009-06-10T12:04:00.001-05:002009-06-10T12:14:21.049-05:00A simple method of binding the selected values of a list in WPF with MVVM<p>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…</p> <p>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.</p> <p>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.</p> <p>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.</p> <p>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:</p> <pre class="brush: xml;"><ListBox ItemsSource="{Binding PersonCollection}" <br /> SelectionMode="Multiple" ><br /><br /> <ListBox.Resources><br /> <Style TargetType="{x:Type ListBoxItem}"><br /> <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/><br /> </Style><br /><br /> <DataTemplate DataType="{x:Type MultiSelectMvvm:Person}"><br /> <StackPanel Orientation="Horizontal"><br /> <Label Content="{Binding Name}"/><br /> <Label Content="{Binding IsSelected}"/><br /> </StackPanel><br /> </DataTemplate><br /> </ListBox.Resources><br /><br /></ListBox><br /><br /><CheckBox IsChecked="{Binding SelectAll}" Margin="3"><br /> Select All<br /></CheckBox></pre><br /><br /><p>Here is the ViewModel code: </p><br /><br /><pre class="brush: csharp;">using System;<br />using System.Collections.Generic;<br />using System.ComponentModel;<br />using System.Linq;<br />using System.Text;<br />using System.Collections.ObjectModel;<br /><br />namespace MultiSelectMvvm<br />{<br /> public class Window1ViewModel<br /> {<br /> ObservableCollection<Person> personCollection;<br /> public ObservableCollection<Person> PersonCollection<br /> {<br /> get<br /> {<br /> if (personCollection == null)<br /> {<br /> personCollection = new ObservableCollection<Person>();<br /> }<br /> return personCollection;<br /> }<br /> set { personCollection = value; }<br /> }<br /><br /> private bool selectAll;<br /> public bool SelectAll<br /> {<br /> get<br /> {<br /> return selectAll;<br /> }<br /> set<br /> {<br /> selectAll = !selectAll;<br /> foreach (var person in personCollection)<br /> {<br /> person.IsSelected = selectAll;<br /> }<br /> }<br /> }<br /> }<br /><br /><br /> public class Person : INotifyPropertyChanged<br /> {<br /> public string Name<br /> {<br /> get;<br /> set;<br /> }<br /><br /> private bool? isSelected;<br /> public bool? IsSelected<br /> {<br /> get<br /> {<br /> return isSelected;<br /> }<br /> set<br /> {<br /> isSelected = value;<br /> NotifyPropertyChanged("IsSelected");<br /> }<br /> }<br /><br /> public event PropertyChangedEventHandler PropertyChanged;<br /><br /> private void NotifyPropertyChanged(String info)<br /> {<br /> if (PropertyChanged != null)<br /> {<br /> PropertyChanged(this, new PropertyChangedEventArgs(info));<br /> }<br /> }<br /> }<br />}</pre><br /><br /><p>FYI: Marlon over at C# Disciples wrote a recent blog post about this: <a href="http://marlongrech.wordpress.com/2009/06/02/sync-multi-select-listbox-with-viewmodel/">Sync Multi Select Listbox with ViewModel</a>.  His approach uses Attached Properties.</p> Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-66046721619722716252009-06-09T13:57:00.002-05:002009-06-09T20:00:53.417-05:00Microsoft paying to advertise Bing on Google?!?!I found this <span id="SPELLING_ERROR_0">hilarious</span> on a variety of levels: Microsoft is paying Google to place ads for it's new <a href="http://bing.com/">Bing</a> search engine on Google (see the screen grab from my Gmail inbox below).<br />
<br />
It has got to cause some serious pain at Microsoft to pay this bill. Did they use Steve <span id="SPELLING_ERROR_1">Balmer's</span> credit card to setup the <span id="SPELLING_ERROR_2">Adwords</span> <span id="SPELLING_ERROR_3">account</span>?<br />
<br />
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.<br />
<br />
<img border="0" fj="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqQgVi9CmpUeEjuoDN9O-7etSw0Ok6JcnFrV2mXFX9tgFF7M6j40Urj1tEqME-k8A2ag05q3_JCALFAgqfvFiq9AKGDwzOeVRR3KwP0Uklnw0oNYeORkAwAE-SNMMcIT26H8lXvCyybDYR/s800/microsoft_ads_on_google.PNG" />Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-11473487754927295812009-04-09T16:19:00.003-05:002009-04-23T11:59:40.018-05:00Silverlight 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:<br /><br /><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNef9LkXuIF9tJP7S48_rAFjcD-ZLM1Trvf1kuvnZfFUPLz5WUGCUxKv_MoZUr0zkQadPG3I6KGF9Rzyek102em4dDyoI8B1uF3P1kpRapoUijn-859ok_72iCovykcC1GABq2jbZKHHM8/+2.png" border="0" /><br /><br />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...<br /><br />UPDATE: The problem site I am trying to access is: <a href="http://blogs.msdn.com/silverlightws/archive/2009/04/08/using-wcf-services-from-silverlight-in-azure.aspx">http://blogs.msdn.com/silverlightws/archive/2009/04/08/using-wcf-services-from-silverlight-in-azure.aspx</a><br /><br />UPDATE #2: Manually installing the Silverlight 3 Beta did solve the problem (the error message was still incredibly unhelpful...)Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com0tag:blogger.com,1999:blog-594392348185533137.post-22484251311527142402009-03-31T12:42:00.000-05:002009-03-31T12:42:32.545-05:00Double-clicking on a ListBox in MVVMHere is a quick code snippet that demonstrates doubleclicking on a WPF ListBox in MVVV. Note: This is using <a href="http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/">AttachedCommandBehavior V2</a>.<br />
<br />
<div class="MsoNormal" style="mso-layout-grid-align: none;"><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"><br />
<</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">ListBox</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> Name</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">="MyListBox"></span></div><br />
<div class="MsoNormal" style="mso-layout-grid-align: none; text-indent: 0.5in;"><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"><</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">ListBox.Resources</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">></span></div><br />
<div class="MsoNormal" style="margin-left: 0.5in; mso-layout-grid-align: none; text-indent: 0.5in;"><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"><</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">Style</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> <br />
TargetType</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">="{</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">x</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">:</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">Type</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> ListBoxItem</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">}"></span></div><br />
<div class="MsoNormal" style="margin-left: 1in; mso-layout-grid-align: none; text-indent: 0.5in;"><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"><</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">Setter</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> <br />
Property</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">="IsSelected"</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> <br />
Value</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">="{</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">Binding</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> <br />
Path</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">=IsSelected,</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> Mode</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">=TwoWay}"/></span></div><br />
<div class="MsoNormal" style="margin-left: 1in; mso-layout-grid-align: none; text-indent: 0.5in;"><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"><</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">Setter</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> <br />
Property</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">="acb:CommandBehavior.Event"</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> <br />
Value</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">="MouseDoubleClick" /></span></div><br />
<div class="MsoNormal" style="margin-left: 1in; mso-layout-grid-align: none; text-indent: 0.5in;"><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"><</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">Setter</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> <br />
Property</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">="acb:CommandBehavior.Command"</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> </span></div><br />
<div class="MsoNormal" style="margin-left: 1.5in; mso-layout-grid-align: none; text-indent: 0.5in;"><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">Value</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">="{</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">Binding</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> ElementName</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">=Window1,</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> <br />
Path</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">=DataContext.MyDoubleClickCommand}" /></span></div><br />
<div class="MsoNormal" style="margin-left: 1in; mso-layout-grid-align: none; text-indent: 0.5in;"><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"><</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">Setter</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> <br />
Property</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">="acb:CommandBehavior.CommandParameter"</span><span style="color: red; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"> <br />
Value</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">="{</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">Binding</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">}" <br />
/></span></div><br />
<div class="MsoNormal" style="margin-left: 0.5in; mso-layout-grid-align: none; text-indent: 0.5in;"><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"></</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">Style</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">></span></div><br />
<div class="MsoNormal"><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"><span style="mso-spacerun: yes;"> <br />
</span></span><br />
<span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"><br />
</</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">ListBox.Resources</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">></span></div><br />
<div class="MsoNormal"><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;"></</span><span style="color: #a31515; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">ListBox</span><span style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-no-proof: yes;">></span></div><br />
Key points to note:<br />
<ul><li>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?".</li>
<li>Using a Style is a quick way to insert the stuff we want into each ListBoxItem.</li>
<li>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...)</li>
</ul>Eric Bowenhttp://www.blogger.com/profile/16365330785571984254noreply@blogger.com1