tag:blogger.com,1999:blog-126457662024-03-06T06:27:45.993+08:00Ramblings of a pom in Perth.Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.comBlogger40125tag:blogger.com,1999:blog-12645766.post-37099797092707483722014-01-14T14:43:00.000+08:002014-01-14T19:54:02.177+08:00Azure Active Directory, Xamarin and OAuth2This is one of those posts where I’m brain dumping my findings.<br />
In a nutshell, I wanted to write a Xamarin App which authenticates against a Windows Azure Active Directory (WAAD) and then access a Web Api which is secured using WAAD.<br />
There are quite a lot of tutorials out there but most use ADAL (<a href="http://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/">Active Directory Authentication Library</a>) to handle the OAuth2 which isn’t a Portable Class Library. I grabbed the Xamarin.Auth library which abstracts the OAuth2 <strike>protocol</strike> framework away from me a bit.<br />
So I followed the instructions here (<a href="http://www.cloudidentity.com/blog/2013/07/23/securing-a-web-api-with-windows-azure-ad-and-katana/">http://www.cloudidentity.com/blog/2013/07/23/securing-a-web-api-with-windows-azure-ad-and-katana/</a>), plumbed in the values to the OAuth2Authenticator class,<br />
<pre class="csharpcode"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2DNktcwyrS_LpWo1m7wg_lKgsJfd3_JgAuiOxwDGs0mzZJPGShAfsnQW2rS2RjgfP9cVsFA__nLf_c2LngT2rdoqoXsDNDGHIAFUIK42ohhHjamQ0SnLazA0evjT4sC_i17OP/s1600-h/image4.png"><img alt="image" border="0" height="181" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDaSN0jPYemGjhg_tEMZw9-61pH8V54rpo099AC8Njo27-8s1iOCw7SxDbGFYN_lZqXeZ-Q6mWySjZN2sJ6JVjVPc4Mrv4kPMOJrZ4ROlEyTkAci668EgMcg7Gj-tyvHxKZ2Cr/?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline;" title="image" width="444" /></a> </pre>
<br />
<style type="text/css"><br /><br /><br /><br />.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }</style><br />
<br />
<br />
<br />
and… Nothing.. Failure.. <br />
<br />
<br />
So, here’s what I’ve learnt about OAuth2 in Azure Active Directory (as of 10/Jan/2014).<br />
<br />
<br />
When we are a Native Client with no client secret, Azure AD does not use OAuth2’s implicit flow where we get a token immediately. It uses the code grant flow where after authenticating we are given a code which we swap for a token.<br />
<br />
<br />
When we initially get the code we need to pass another querystring parameter called “resource” which identifies the Application in Azure Active Directory that we want to call. This resource is the App Id Uri on Azure’s portal. And from what I can see, we don’t need to pass a scope.<br />
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgAIwdt9wV-z4k6NCBBZwnhbZYfEKcXO2HJbViyH0-9yK0W4N7ACAF928OenGccbLLPPHxU6RuhV8ycw6At16XdJDWqDhBfvj2GoGE2XDAColcTrdsOANudAb-OQduuBeDdY1f/s1600-h/image9.png"><img alt="image" border="0" height="114" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOxSKCWqBGak-m5e2xk_mvZj1vrV-M2d_hnVINpTj_ipj486F6wsK40Ja0JhrHeeZ0bUhltoEHFCZFGOhIahMu-Ei_90UQ_X1gcv5Zrf_lyNmiD56NmGbWaJKkWAOz58hqG80o/?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline;" title="image" width="590" /></a> <br />
<br />
<br />
And when we’ve finally got the token it needs to go as a Bearer token in the headers of subsequent requests. This is written in the spec, but for whatever reasons the Xamarin.Auth component seems to put it on the querystring.<br />
<br />
<br />
So the main difference from most of the OAuth2 implementations seems to be getting that initial code. The Uri you need is:<br />
<br />
<br />
<a href="https://login.windows.net/%3Ctenant%3E/oauth2/authorize?client_id=%3Cclient%3E&resource=%3Capp_id_uri_from_waad%3E&redirect_uri=%3Credirect_uri_from_waad%3E&state=%3Crandom%3E&response_type=code" title="https://login.windows.net/cfec9f66-9516-451c-b72c-7c79905e5e4e/oauth2/authorize?client_id=f1ec787b-d109-4b84-ab42-cf660cfb1e74&resource=https://graemefosterhotmail.onmicrosoft.com/apitest&redirect_uri=http://graemefoster.com/login_success&state=123456789&response_type=id_token&nonce=adfhjsdfgfd">https://login.windows.net/<tenant>/oauth2/authorize?client_id=<client>&resource=<app_id_uri_from_waad>&redirect_uri=<redirect_uri_from_waad>&state=<random>&response_type=code</a>Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com7tag:blogger.com,1999:blog-12645766.post-22252634575837517702012-09-27T13:57:00.001+08:002012-09-27T14:00:03.231+08:00Continuous Azure Deployment via TFS Preview<p> </p> <p>I’ve spent a lot of time recently working with Windows Azure, and it’s been a good time to be there. The Azure team have been releasing some awesome new features around the ALM space and one in-particular got my interest – the ability to push to Azure from TFS Preview, the new online TFS Service being pushed out by Microsoft.</p> <p>It’s super simple to do, but really powerful. I love automated deployments and having the ability to push a new version of a site out purely by checking in is great.</p> <p>This post runs through, step by step, what you’ll need to do to get it going.</p> <p>First though, you need to get a TFS Preview account, and a Windows Azure account. These are super simple to setup. Just go to <a href="http://tfspreview.com/">http://tfspreview.com/</a> where you can register for a TFS Preview account, and then hop to <a href="http://windowsazure.com">http://windowsazure.com</a> to get a free trial of Azure.</p> <p>Got them? Great. Here’s a summary of what we are about to do.</p> <p>1. Create a new Team Project on TFS Preview</p> <p>2. Create a new Web Site in Visual Studio.</p> <p>3. Create a new Web Site in Azure and link it up to our TFS Project</p> <p>4. Check-in some code and watch the site build, deploy, and be ready to access.</p> <h3>Create a new Team Project on TFS Preview</h3> <p>Like everything in this post, it’s super simple. </p> <p>Browse to <a href="https://{your account}.tfspreview.com/">https://{your account}.tfspreview.com/</a> </p> <p>When you’re there click on the link to Create a new Team Project. You’ll be presented by the dialogue shown below. I’m going to accept the default template. Just give the project a name, click on ‘Create Project’ and this bit is done.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvamXOc-OLruEkxsTz3RU-3QWpqLXM3XqKfRO9sIsG6c4BYtJklNBKEQCR5dm3ao4ukKwBLCTNHiAOfNdjtqkvEc9BKjitwOvasCy-_zn_lSIsJvv7i2iOk1cYXjV9WuXD1Bsa/s1600-h/New-Team-Project%25255B5%25255D.png"><img title="New-Team-Project" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="New-Team-Project" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgU4KH1R6Uj4cJzozvGJxuaTXDUnMr4EMbdpeE80nYu20G8YT8zxSwgxLMrpzPjdz8UUJKuuKljG90vqlqKB5dOfX1wdzF15iMFWbA-tzT8PD5yqX1h3B8fZVck0MZ42X1PH-Kn/?imgmax=800" width="514" height="368" /></a></p> <h3>Create a new Website in Visual Studio</h3> <p>This bit is pretty simple. I’m going to create a new MVC 4 Web Application. You can choose a pre-configured template if you like. I’ve chosen an empty one and will add the most basic Controller to get some content active. I’ll link to my code at the end of the article.</p> <h3>Check into TFS Preview</h3> <p>Are you still with me? Great. Now what we need to do is hook Visual Studio up to TFS Preview.</p> <p>From the Team Explorer window we can connect to a new Team Project. From here its a simple case of entering your TFS Preview account details, and selecting the Team Project that was created earlier.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEic0AxocYj59N55SXbbLIX0kdlNfWdn8SVssrPRW_gR80R_Zs09dWzpSXyylwhTR5UCMZytDQfGPAI0tD6JJihFEuNmwBKJXFJ1Zqi8Lwz_flCTg4REd9-K4xaiaMzjqtKO1TIH/s1600-h/image%25255B8%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH8TaU0SDitN4Ce94DRKWt9_PRKg6ZkKUuAYyGjh9qmtq3in8ManTOrbXaP6HhBw8ih6v5lMeTq0_ZeENYwrnzTwUWXosRf8u-Yi8yLnhAdE02ROLALIsyhaCjNCN95uwqH6P1/?imgmax=800" width="386" height="192" /></a></p> <p>Once connected we can add the Solution to source control.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAYeMr_20BzEd6rw7YVfdnU69t4FozMLcEBM4jkVRZa7ed-yG7ywIezXtPS1Pb_llCfKmjlSWldyNWXF3x_DuqHyxbMkhZUP3HkwA2SB-gkgf2a3II6JqWWPCd6nw45eCWwsFO/s1600-h/image%25255B12%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhn3fwUODkN0v6TueVkkjacWka4aPFu8HQquKwDfxmWwtZwaiOf-RVVwG7qiIWSk23b2fIcrjDuaum-VLayzXC3Wo5P07bOTyRcWyGj3fb1NCTog4Jk-4sOC3vG9gn1Hio5OSAG/?imgmax=800" width="538" height="333" /></a></p> <p>This will pick up a set of ‘pending changes’ which are files that Visual Studio believes need to be checked into TFS. Add a comment, check-in, and let’s go to Azure and setup a Website. I like using the new Azure Preview HTML 5 site which is at <a href="https://manage.windowsazure.com">https://manage.windowsazure.com</a>. When you’re in, select Web Sites, and “Create a Web Site”.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP8L8EG2WbH939N7yVJthuPp0xlbCsCZ1vTx7KczsCYlrVEUlseYt7bN-_MiwpD6e9cXPpOa_6FPyrkJuuUT2TJcmARsYud5O76MxCVdGejOHZsMocydSEjBCPN7LN8luSnbiM/s1600-h/image%25255B20%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ21qSiiXTm_s06bnD_Y-O6_Lv_baMFe1XkhDnBzs5w1tMuCVZzM3KRKkVZptWaNFKBjondFwFFJOkL8vYdFh90JI5tf1WDwInqMEitGFuexRekFKH-A9xRK6O0lYEokXtr2Df/?imgmax=800" width="661" height="209" /></a></p> <p>Enter a name and region on the dialogue that appears, and hit ‘OK’. When its created select it. Azure will take us to a Dashboard for the new web-site where we can setup TFS Source Control.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEif7TMuweQfpXEdcFA9fXZYeiPpJjQRNAhJ-c3Z-_29KpQesBdqJKgLOWJPFfmrLsjKtQcvjSpaeqEFBE3KjaKx2sealR2kK-ECvlPpp0BfmxuZyFIR8g4VQNdue_Utogu0NFUF/s1600-h/image%25255B25%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwFU0-LeXXYWMbreveBzQWRadKL8t6E2Nl92aiWf0gBIB0-szuO8rC8NcXaaHwq3_kUzB9iruR2dZfIvcj2CYg_-y3cigoJZV2jTk9ifz_Qn4eOdUvjEyGm9nzJ794Upmf_1jB/?imgmax=800" width="532" height="428" /></a></p> <p>You need to select “Set up TFS publishing”. A dialogue will appear to get authorisation to access TFS Preview from Azure. Fill in your TFS Preview credentials. Eventually a dialogue appears asking you to select which Team Project you wish to publish. Just select the one we created earlier.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJefgdfQYgC_nG5FYJWjqsdghgGKqyI8XSoTkFLd1ubrXrwo5aipfjTFu4Pns7nTB-gIdiyhfTbiAEIgpM19rD5fwcRFiNI1xMLb-CQA8XTJsLkfoh54-yUxq2gnTEHpos3MaS/s1600-h/image%25255B30%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5g-lT5mD1ryhC_a6LAQJtUlaObTrVqtpYULS3kThMYwvTpuVKvEAiCKmGdcA7pX8idZbJs7gNqO1_piV33nbZuenYYtfdhsljwF9SocOnGIogGX_f2V2ZuWiphmG9HRD7XQC6/?imgmax=800" width="490" height="409" /></a></p> <p>Any check-ins will now trigger a build in TFS Preview and, on success, a push to Azure.</p> <p>So try it – check in a file and navigate to the Builds section on TFS Preview. You should see something similar to this:</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN5DZTrjukrE0qE8US2befrobgiThpC3f3OmCHMZBeg_uJR54bK6kE2331WL7c1RjL7Rfv3jIFmayhNhziRd-bj72zo6D608UKF2keix7dfIjkoDb-IMKNbOckCi2aeAKD11Yv/s1600-h/image%25255B35%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlaL8jZUYw0uU08O6gaPhuTUvovkpT0FB-H-UiYc9iXBK_55ORhirtv5bUPevYTq9Db4xu3K75IKNhvbofi6fEdd1FyPuzj8g0G9infx8TZNag88BUfdhzWWvu1ACQXZeE0UPY/?imgmax=800" width="752" height="204" /></a></p> <p>And if all goes well you should then see this:</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8JlSODYEZIXowtmu0xZF0OyZ9rHIWp6Ut7NEP0X-Wa5-Rhdai-EHOztpTChnyoC9GC5GcwQP_kH8ZZOFJjLWlgs7IZtbDpDp0OYkuYVzEZTaEC12bC2-cDxaHLGJVSYDh-ClM/s1600-h/image%25255B39%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYtKOfmbGamq74wyljEgKgCH-gmTC2nj-qHyCLfBaSAt0UT8TMOlQYnKTPpb-t1RA7EBF0z6FSv0mD6VtDIz559XZLU59l5UHd5Ish9H-By3ZOUKKG0f9Cq_gMd7PZMJMxl9em/?imgmax=800" width="452" height="161" /></a></p> <p>Once the build has succeeded, the automatic publish to Azure will kick in. If you flick to your Azure portal you’ll be greeted with this screen:</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsCRFWyqtcvueMm4HFFd7okd9MLuhPalsqN4Gw8SOsL788N80bgGAbBu-elEAwTXKWmbK8J1djjiQQYW8IyVXW0EkDHn9mjnaoDCc3IGsyMPjcVIaFkKCVG32_kI2vfAsOf-qk/s1600-h/image%25255B44%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhT5xvHexc8QU55nQVRAbQQ32cFDxr0oaFFnGWovfIzhrqz_eEv8phfmohuWpa30X5xRWJRdGR4lRVLAfSlgIupk5NjHwMTEOLo5ElIqA0OxoE0HUDi6T1HFFL9X6low0R9mCCv/?imgmax=800" width="610" height="245" /></a></p> <p>And that’s it! You’ve successfully pushed a change to TFS Preview which has kicked off a build in the cloud, followed by an automatic push to a Windows Azure Website.</p> <p>Congratulations <img class="wlEmoticon wlEmoticon-openmouthedsmile" style="border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none" alt="Open-mouthed smile" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2ByXGDvznWn6KRCzjonMUooK8KOd8K1vunk8uIoQ8LAf3o9s_I8w21Mrw__Y1o9ViwIj-1f25kPWCqZ4pPq9X5qTtgICa62CWNC1yVdx0e1B-lViOMv-EYA7IacMscdseYBdZ/?imgmax=800" /></p> Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-77582660274840690132010-06-22T19:31:00.004+08:002010-06-22T19:58:07.298+08:00Wpf, Resources and DataContextOne of the frustrating things in WPF is that objects in the Resources Collection can't see the DataContext from their containing control. It makes sense when you think about it as they are not within the Logical / Visual Tree, which Dependency Properties can inherit down. Whilst it doesn't normally affect me, today I came across a need to have this.<br /><br />I've just worked on a view where we want to expose a collection in a next-previous way, and expose a 'CurrentItem' property. Whilst we could have done it in our ViewModel, in our scenario we don't want the ViewModels becoming aware of the next / prev, and just to be aware that they are given a list of items, and one of them is selected.<br /><br />I went down the approach of a control which inherited from FrameworkElement as it had a DataContext then put it in the Resources Collection. Of course this didn't work as as we said at the beginning, stuff in the Resources cannot access the DataContext. BUT back up a minute... there is a control which seems able to do this - the CollectionViewSource. How does it do it? Heh heh, Reflector revealed the internal hack which MS used to somehow ram the inheritence of DP's into this unsuspecting class.<br /><br />Nasty, but it just so happens we can exploit this for our own purposes. CollectionViewSource wraps a collection which it can obtain by binding to the DataContext, and it is not marked as sealed so we can extend it and add our own behaviour.<br /><br />What I ended up doing was subclassing CollectionViewSource and adding a NextCommand, PreviousCommand, and SelectedItem dependency property to my subclass. (side note - we use a OneWayToSource binding to reverse the SelectedItem back onto the ViewModel we can bind to a standard .Net property on the ViewModel).<br /><br />All sounds good, but there was one more issue. The CollectionViewSource is a bit of a liar, in that when you bind to it, you don't actually bind directly to it, but instead to the Collection it exposes. It makes for a nicer syntax in that 99% of times you use it, all you are interested in is that exposed collection. For us though we need to drill into our actual class to get at our subclasses properties. That's where that strange property on Binding, BindsDirectlyToSource comes in. It lets us probe past that outer facade of the class and get into the real object.<br /><br />Our code is not far off being acceptable now. It looks something like:<br /><br /><SummaryContentActionView> <!-- the scaffolding view which uses a template to define the layout --><br /> <br /> <SummaryContentActionView.Resources><br /> <NextPreviousCollection x:Key="col" Items="{Binding Contract.Items}" SelectedItem="{Binding SelectedItem, Mode=OneWayToSource}" /><br /> </SummaryContentActionView.Resources><br /><br /> <SummaryContentActionView.MainContent> <!-- object DP exposed from the scaffold contol --><br /> <StackPanel><br /> <Button Command="{Binding Source={StaticResource col}, Path=NextCommand, BindsDirectlyToSource=True}" /><br /> </StackPanel><br /> </SummaryContentActionView.MainContent><br /><br /><br /></SummaryContentActionView>Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com1tag:blogger.com,1999:blog-12645766.post-26581815285654984782010-06-12T13:30:00.001+08:002010-06-12T13:30:28.950+08:00Fun with NHibernate QueryOver and Linq provider<p>Given the following classes: </p> <p>Blog <br />{ <br />  Guid Id <br />  List<Post> <br />} </p> <p>Post <br />{ <br />  Guid Id <br />  Name <br />} </p> <p>What's the best way to fetch a list of Blog ID's against the count of posts. Without going into HQL I've so-far got 2 ways, one using the Criteria (QueryOVer - nH3.0) and one using the NH linq provider. On a tiny database the results are quite interesting. </p> <p>QueryOver needs to use a detached criteria and sub-select to get the results we need: we have to create 2 aliases, one for the select count bit of the query, and one to select over blog posts. We use a little trick with aliases to correlate the inner query to the outer query (correlated queries). </p> <p>                Blog outerBlogAlias = null; <br />                Blog innerBlogAlias = null; <br /></p> <p>                var innerQuery = <br />                    (QueryOver<Blog, Blog>)session <br />                        .QueryOver(() => innerBlogAlias) <br />                        .Where(() => outerBlogAlias.Id == innerBlogAlias.Id) <br />                        .Inner.JoinQueryOver(o => o.Posts) <br />                        .ToRowCountQuery(); </p> <p>Did you catch the alias bit – QueryOver(() => innerBlogAlias) – the clever bit is we can reference the alias used in the outer query following to correlate the two. That’s the line which reads .Wher(() => outerBlogAlias.Id == innerBlogAlias.Id).  </p> <p>                var outerQuery = <br />                    session.QueryOver(() => outerBlogAlias) <br />                    .Select( <br />                        list => <br />                            list <br />                            .Select(o => o.Id) <br />                            .SelectSubQuery(innerQuery)); </p> <p>This is the outer query – look how we use .SelectSubQuery(innerQuery), to capture the count of all the children posts in the main select statement. Neat huh?</p> <p>OK, wanna see the same in linq-nhibernate…</p> <p>var results2 = session.Query<Blog>() <br />    .Select(o => new <br />                     { <br />                         Id = o.Id, <br />                         PostCount = o.Posts.Count <br />                     }) <br />                     .ToList(); </p> <p>Done! And it even creates an anonymous class to hold the results. The interesting bit is the generated query. The QueryOver actually has to join Blog –> Posts. As a Post doesn’t hold a back reference to a Blog I can’t think of a better way to do this (other than changing the domain model which may or may not be acceptable). No such drama with the linq version though. It goes straight to the Posts table.</p> <p>The lack of the extra join in a table with ooo, 8 posts, means that the QueryOver takes 61% of the query time (in sql), whilst the linq version only sucks up 39% of the overall time. Sql’s query plan for the QueryOver version shows that Sql Serve has to perform more work.</p> <p>So what’s my conclusion – it’s that linq-nh, and queryover, are both really cool powerful query mechanisms. Each can do things the other can’t do, and you should not discount either of them up-front. Use the right query tool for the right job… And of course I should take my own advice and learn HQL as-well! For the record the reason I haven’t is that both QueryOver and Linq-NH are type-safe which is something I really like.</p> Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com1tag:blogger.com,1999:blog-12645766.post-34261331499831422432010-01-02T15:43:00.001+08:002010-01-02T15:43:01.372+08:00C# to iPhone Objective-C<p>This set of blog posts is more for my own memory than anything else. I’m playing with iPhone development and wanted to draw similarities as-well as write down things I learn whilst getting to grasp with Objective-C.</p> <p>So here we go. Let’s start at the beginning by looking at some core differences between the 2. The order might be a bit rambling but that’s just me writing stuff down that drops into my head! Soon I’ll try get onto the more visual aspects of iphone development but I think it’s essential to get your head around how to structure objective-c code before diving into guis.</p> <p>For the record I learnt a lot from Dr Google, and this website was especially good: <a href="http://www.otierney.net/objective-c.html">http://www.otierney.net/objective-c.html</a></p> <p>1. Almost everything is a pointer.</p> <blockquote> <p>To ‘create’ an instance of an object in Objective-C we tend to have 2 choices. The first involves ‘allocating’ memory for the object then ‘initialising’ it in some way. The 2nd involves calling a factory (think static) method on a class.</p> <p>Whichever we do what we end up with is a pointer to an object. In Objective-C we must explicitly show this by using the * character. So to create an NSString object (a fairly core object) we can say:</p> <p><font face="Courier New">NSString* myString = [NSString alloc]; </font></p> <p>more on the syntax in a minute.</p> <p>To create the string object with a value:</p> <p><font face="Courier New">NSString* myString = [[NSString alloc] initWithString: @”Hello” ];</font></p> <p>Or you can say:</p> <p><font face="Courier New">NSString* myString = [NSString stringWithString: @”Hello”];</font></p> <p>The 1st two use instance methods on the NSString to initialize it. The 2nd uses a factory method to create the string. The main difference between the 2 is that by explicitly allocating the string (the 1st way) you are responsible for releasing the memory. With the 2nd way you aren’t. I’ll leave the specifics for another post as it deserves more time!</p> </blockquote> <p>2. Calling a method on an object.</p> <blockquote> <p>In C# / Java this is done via the dot (.) notation. So to call method Foo on object bar we say bar.Foo(). If we want to pass parameters to this method call we put them inside the parenthesis. So bar.Foo(someParameter);</p> <p>Objective-C talks in terms of messages instead of method calls but for this example lets think of them as the same sort of idea. There are reasons for this as we’ll see soon. The syntax is weird at first sight - </p> <p><font face="Courier New">[bar Foo]; </font></p> <p>means the same as bar.Foo(); in C# and </p> <p><font face="Courier New">[bar foo: someParameter] </font></p> <p>is the equivalent of bar.Foo(someParameter);</p> </blockquote> <p>As you can see Objective-C looks a bit confusing at 1st sight especially if you’ve used C# Attributes before which use a square bracket notation.</p> <p>3. Declaring a method on an object.</p> <blockquote> <p>Objective-C uses Interface (header) files to declare members, methods, properties etc. that will appear in the class body. So you have 2 files. A .h and a .m file. </p> <p>To declare a method we must add its signature to the .h file, and the contents of it to the .m file. Using the Foo.Bar(someParameter method) we end up with:</p> <p><u>.h file</u></p> <p><font face="Courier New">- [void] Bar: (NSString*) theParameter</font></p> <p>.m file</p> <p><font face="Courier New">- (void) Bar: (NSString*) theParameter</font></p> <p><font face="Courier New">{</font></p> <p><font face="Courier New">   //do something</font></p> <p><font face="Courier New">}</font></p> </blockquote> <p>In a nutshell </p> <p>the minus sign denotes an instance method rather than a class (static) method which would use a + sign.</p> <p>[void] is the return value. In this case my method returns nothing.</p> <p>Bar is the name of the method (followed by colon if there are parameters).</p> <p>Then come the parameters. In this case I’m asking for an NSString* where the * means a pointer. Objective-C pretty much uses pointers for everything other than primitive values (int, float, etc). So-far (heh heh caveat alert) I haven’t seen a pointer being de-referenced explicitly as in C++.</p> <p>To send multiple parameters is a bit weird:</p> <p><font face="Courier New">- (void) setLatitude: (int) latitude andLongitude: (int) longitude <br /></font><font face="Courier New">{ <br /></font><font face="Courier New">}</font></p> <p>This method requires 2 integers. ‘latitude’ and ‘longitude’. To call this method we’d write:</p> <p><font face="Courier New">[myFoo setLatitude: 98 andLongitude: 50];</font></p> <p>Looks a bit bizarre huh?!</p> <p>OK that’s enough for today. Next time I’ll try write about some other fundamentals – especially memory management (iphone’s version of Objective-C doesn’t have Garbage Collection).</p> Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-37693326919924395732009-06-17T13:52:00.001+08:002009-06-17T13:58:29.555+08:00Creating an Ellipsis (...) TextBlock in Silverlight.<p>So I recently had the requirement to truncate text in a Silverlight TextBlock when it is too wide to fit, and suffix it with '...'. Easy I thought - hah hah you didn't bet on Silverlight though! I thought I could do some things around </p> <p>1. MultiBindings - bind the actualwidth of the textblock, and the string property. Pass them into a IMultiValueConverter and work out how much text can be shown. Unfortunately SL doesn't support Multi Bindings. Pah.</p> <p>2. Subclass TextBlock. I hate using inheritance to solve these sorts of problems - I don't want to force people to use my own version of TextBlock - what if for some reason TextBlock gets extended in future and I've killed the inheritance tree. </p> <p>3. Explicity grab the TextBlock in the code-behind and have a helper function to set the text whenever it changes. I’m working against ViewModels and want to keep my code-behind empty so whilst this might work it’s not what I’m looking for.</p> 4. Attached Properties - the old attached behaviour via attached property trick. That’ll save the day – and here’s how it works: <br /> <p>My first thought was an attached behaviour that would somehow get hold of the Binding, stash it, monitor it for changes, and create a new Text binding which would get the text with ellipsis where appropriate. SL doesn't allow you to get the underlying Binding though. Only set it. Pah.</p> <p>So I decided Converters would be involved. Again, the problem was that I couldn't get the underlying Binding so I decided to make my one SL concession which was to ask the user of my new behaviour (EllipsisText) to pass me the Property they want to bind to as a string, instead of using a binding markup expression. </p> <pre class="code"><span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>EllipsisTextPropertyNameProperty =<br /> <span style="color: #2b91af">DependencyProperty</span>.RegisterAttached(<br /> <span style="color: #a31515">"EllipsisTextPropertyName"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">string</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">EllipsisTextBoxBehaviour</span>),<br /> <span style="color: blue">new </span><span style="color: #2b91af">PropertyMetadata</span>(<span style="color: blue">null</span>, OnEllipsisTextChanged));</pre><br /><a href="http://11011.net/software/vspaste"></a><br /><br /><p>When this value is set I want to create a new Binding which will use a Custom Converter. The converter will need to know about the TextBlock though so it can get the maximum Width we have to play with.</p><br /><br /><pre class="code"><span style="color: blue">private static void </span>ConfigureEllipsis(<span style="color: #2b91af">TextBlock </span>textBlock, <span style="color: blue">string </span>propertyName)<br />{<br /> <span style="color: blue">var </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">Binding<br /> </span>{<br /> Converter = <span style="color: blue">new </span><span style="color: #2b91af">EllipsisTextConverter</span>(textBlock),<br /> Path = <span style="color: blue">new </span><span style="color: #2b91af">PropertyPath</span>(propertyName)<br /> };<br /> textBlock.SetBinding(<span style="color: #2b91af">TextBlock</span>.TextProperty, binding);<br />}</pre><br /><br /><p>Finally the converter – it is pretty simple. It takes the width of the TextBlock, then begins to measure how big the block would have to be to show the whole text. I do this by creating a new textblock, setting the font, etc to the same as the target one, setting the Text to the full string, then telling it to measure itself:</p><br /><br /><pre class="code"><span style="color: blue">var </span>textBlock = <span style="color: blue">new </span><span style="color: #2b91af">TextBlock<br /> </span>{<br /> Text = textToFit,<br /> FontFamily = _textBlock.FontFamily,<br /> FontSize = _textBlock.FontSize,<br /> FontStretch = _textBlock.FontStretch,<br /> FontStyle = _textBlock.FontStyle,<br /> FontWeight = _textBlock.FontWeight<br /> };</pre><br /><a href="http://11011.net/software/vspaste"></a><br /><br /><pre class="code">textBlock.UpdateLayout();</pre><br /><br /><p>I can then begin to check the ActualWidth of this textblock against the width of the target one. Start chopping bits of the string (of course suffixed with ‘…’ when necessary) until the text fits in the allowed width. The TextBlock you are binding against needs an explicit Width set for this to work. The Layout pass hasn’t run when the converter fires and we need a Width to work with.</p><br /><br /><p>To use this all you have to do is:</p><br /><br /><pre class="code"><span style="color: blue"><</span><span style="color: #a31515">TextBlock </span><span style="color: red">Width</span><span style="color: blue">="60" </span><span style="color: red">BehaviourExtensions</span><span style="color: blue">:</span><span style="color: red">EllipsisTextBoxBehaviour.EllipsisTextPropertyName</span><span style="color: blue">="BindingProperty" /></span></pre><br /><a href="http://11011.net/software/vspaste"></a><br /><br /><p>Full code:</p><br /><br /><pre class="code"><span style="color: blue">public static class </span><span style="color: #2b91af">EllipsisTextBoxBehaviour<br /></span>{<br /> <span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>EllipsisTextPropertyNameProperty =<br /> <span style="color: #2b91af">DependencyProperty</span>.RegisterAttached(<br /> <span style="color: #a31515">"EllipsisTextPropertyName"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">string</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">EllipsisTextBoxBehaviour</span>),<br /> <span style="color: blue">new </span><span style="color: #2b91af">PropertyMetadata</span>(<span style="color: blue">null</span>, OnEllipsisTextChanged));<br /><br /> <span style="color: blue">private static void </span>OnEllipsisTextChanged(<span style="color: #2b91af">DependencyObject </span>d, <span style="color: #2b91af">DependencyPropertyChangedEventArgs </span>e)<br /> {<br /> <span style="color: blue">var </span>textBlock = d <span style="color: blue">as </span><span style="color: #2b91af">TextBlock</span>;<br /> <span style="color: blue">var </span>propertyName = e.NewValue <span style="color: blue">as string</span>;<br /> <span style="color: blue">if </span>(textBlock != <span style="color: blue">null </span>&& e.NewValue <span style="color: blue">is string</span>)<br /> {<br /> ConfigureEllipsis(textBlock, propertyName);<br /> }<br /> }<br /><br /> <span style="color: gray">/// <summary><br /> /// </span><span style="color: green">Creates a new binding on the text property.<br /> </span><span style="color: gray">/// </summary><br /> </span><span style="color: blue">private static void </span>ConfigureEllipsis(<span style="color: #2b91af">TextBlock </span>textBlock, <span style="color: blue">string </span>propertyName)<br /> {<br /> <span style="color: blue">var </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">Binding<br /> </span>{<br /> Converter = <span style="color: blue">new </span><span style="color: #2b91af">EllipsisTextConverter</span>(textBlock),<br /> Path = <span style="color: blue">new </span><span style="color: #2b91af">PropertyPath</span>(propertyName)<br /> };<br /> textBlock.SetBinding(<span style="color: #2b91af">TextBlock</span>.TextProperty, binding);<br /> }<br /><br /> <span style="color: blue">public static void </span>ClearEllipsisTextPropertyName(<span style="color: #2b91af">DependencyObject </span>obj)<br /> {<br /> obj.ClearValue(EllipsisTextPropertyNameProperty);<br /> }<br /><br /> <span style="color: blue">public static string </span>GetEllipsisTextPropertyName(<span style="color: #2b91af">DependencyObject </span>obj)<br /> {<br /> <span style="color: blue">return </span>(<span style="color: blue">string</span>)obj.GetValue(EllipsisTextPropertyNameProperty);<br /> }<br /><br /> <span style="color: blue">public static void </span>SetEllipsisTextPropertyName(<span style="color: #2b91af">DependencyObject </span>obj, <span style="color: blue">string </span>text)<br /> {<br /> obj.SetValue(EllipsisTextPropertyNameProperty, text);<br /> }<br /><br /> <span style="color: blue">private class </span><span style="color: #2b91af">EllipsisTextConverter</span>: <span style="color: #2b91af">IValueConverter<br /> </span>{<br /> <span style="color: blue">private readonly </span><span style="color: #2b91af">TextBlock </span>_textBlock;<br /><br /> <span style="color: blue">public </span>EllipsisTextConverter(<span style="color: #2b91af">TextBlock </span>textBlock)<br /> {<br /> _textBlock = textBlock;<br /> }<br /><br /> <span style="color: blue">public object </span>Convert(<span style="color: blue">object </span>value, <span style="color: #2b91af">Type </span>targetType, <span style="color: blue">object </span>parameter, <span style="color: #2b91af">CultureInfo </span>culture)<br /> {<br /> <span style="color: blue">if </span>(_textBlock.Width == 0)<br /> {<br /> <span style="color: blue">return </span>value;<br /> }<br /><br /> <span style="color: blue">string </span>textToFit = value <span style="color: blue">as string</span>;<br /> <span style="color: blue">if </span>(textToFit != <span style="color: blue">null</span>)<br /> {<br /> <span style="color: blue">var </span>textBlock = <span style="color: blue">new </span><span style="color: #2b91af">TextBlock<br /> </span>{<br /> Text = textToFit,<br /> FontFamily = _textBlock.FontFamily,<br /> FontSize = _textBlock.FontSize,<br /> FontStretch = _textBlock.FontStretch,<br /> FontStyle = _textBlock.FontStyle,<br /> FontWeight = _textBlock.FontWeight<br /> };<br /><br /> <span style="color: blue">int </span>charsToChop = 0;<br /> <span style="color: blue">bool </span>needsEllipsis = <span style="color: blue">false</span>;<br /> <span style="color: blue">do<br /> </span>{<br /> textBlock.Text = textToFit.Substring(0, textToFit.Length - charsToChop) + (needsEllipsis ? <span style="color: #a31515">"..." </span>: <span style="color: #a31515">""</span>);<br /> textBlock.UpdateLayout();<br /><br /> charsToChop++;<br /> needsEllipsis = charsToChop > 0;<br /><br /> } <span style="color: blue">while </span>(<br /> charsToChop < textToFit.Length &&<br /> textBlock.ActualWidth > _textBlock.Width);<br /><br /> <span style="color: blue">return </span>textBlock.Text;<br /> }<br /> <span style="color: blue">return </span>value;<br /><br /> }<br /><br /> <span style="color: blue">public object </span>ConvertBack(<span style="color: blue">object </span>value, <span style="color: #2b91af">Type </span>targetType, <span style="color: blue">object </span>parameter, <span style="color: #2b91af">CultureInfo </span>culture)<br /> {<br /> <span style="color: blue">throw new </span><span style="color: #2b91af">NotImplementedException</span>();<br /> }<br /> }<br /><br />}</pre><br /><a href="http://11011.net/software/vspaste"></a> Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com4tag:blogger.com,1999:blog-12645766.post-60812745928078542542009-01-21T20:29:00.002+09:002009-01-21T20:49:50.195+09:00Extending Asp.Net Dynamic DataI recently had a requirement to quickly expose a database table via a web-page to allow some editing of data. Ah-ha I thought, lets see if we can get something for free. Being a .Net kind of bloke I decided the new Dynamic Data framework which ships with .Net 3.5 SP1 would be perfect.<br /><br />Part of my requirement was not to allow inserts / deletes to the tables. Only updates. Pretty simple because you have access to the aspx / ascx templates and can literally remove the buttons / links and change the data sources to not allow inserts / deletes just for added protection to hand-crafted http posts.<br /><br />You can create partials of the classes generated by Linq-Sql and attach attributes like MetadataType, or DisplayName to change the name of the table in the generated pages, or switch off columns from the dynamic scaffolding. You can also change columns in the linq-sql model to make them read-only. Nice :o) All is good in the world!<br /><br />Not so fast though! The next requirement of course was to expose a table which absolutely must be inserted / deleted into. Damn! There didn't appear to be an in-built way to allow insert / delete for some tables but not others (not that I could see). But the answer was simple (so if there is an in-built way I don't have much code to change!!) and here's how I did it.<br /><br />The template asp.net pages all have a MetaTable instance injected into it which amongst other things exposes an Attributes collection. These attributes are the Attributes from the table-model class, in my case the MetadataType / DisplayName attributes. So all you have to do is create another attribute, slap it on the partial classes, and pick it up from MetaTable.Attributes. In my case I created an attribute with two boolean properties, CanInsert and CanDelete. I also added an extension method to the MetaTable class, again CanInsert and CanDelete. The extension methods runs a quick query over the attributes to see if the attribute is there, and if so what the boolean value is. It looks something like this:<br /><br /><tt><br />public static class MetaTableExtensions<br />{<br /> public static bool CanInsert(this MetaTable table)<br /> {<br /> var attribute = table.Attributes.OfType<TableExtensionAttribute>().FirstOrDefault();<br /> if (attribute == null)<br /> {<br /> return false;<br /> }<br /> return attribute.CanInsert;<br /> }<br />}<br /></tt><br /><br />The asp.net template pages can now easily look for this attribute in for example the OnRowDataBound event of lists, and make a decision on whether or not to show a Delete button / Insert link.<br /><br />Simple but effective.Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-29580373233578461412009-01-15T19:45:00.002+09:002009-01-15T20:19:11.320+09:00Hand-crafted IOC in Asp.Net MVCIOC seems to be a bit of a buzzword again recently with frameworks like Asp.Net MVC popping up allowing the possibility of plugging custom Controller Factory objects directly in.<br /><br />That's great, but sometimes you just don't want the baggage of a Container hanging around, especially if you are writing a small-ish solution. I faced that scenario today and stumbled upon what I think is a really elegant solution!<br /><br />The problem... I want to inject dependencies into Controller classes, but don't want to use a container.<br />The solution... OK, bear with me it's easy!<br /><br />In the global application_onstart method I have the opportunity to construct a custom ControllerFactory and pass it to Asp.Net. I won't cover that. Try <a href="http://haacked.com/archive/2007/12/07/tdd-and-dependency-injection-with-asp.net-mvc.aspx">here</a> for more information. <br /><br />My initial thought was to have a ControllerFactory expose a <tt>Register<T>(string name) where T:Controller</tt> method. That would let me register a Controller against a name, and then do an Activator.CreateInstance to create it. But of course in the real world the whole point of IoC is that the Controller will have dependencies it needs satisfying so this approach is kind of lacking!<br /><br />One option I thought of was to have a Builder class for each Controller which would know how to create its Controller. I could <tt>RegisterBuilder<T>(Builder<T> builder) where T:Controller</tt>. Now my ControllerFactory can grab the appropriate builder and just ask it to Build(). The builder would be specific to a Controller so can create it concretely. It works, but it could lead to an explosion of Builder classes.<br /><br />Then I remembered my old friend Func<>. It's nothing new really and is just a concrete implementation of a Delegate we could have written in .Net 2.0 - delegate T Func<T>() I think is the signature- don't have Reflector to hand. It allows me to do something like this:<br /><br /><tt><br />ControllerFactory.Register<T>(Func<T> buildController) where T:Controller.<br /></tt><br /><br />My global.asax can now look something like this<br /><br /><tt><br />var provider = new DbConnectionProvider(Configuration.ConnectionStrings[....]);<br />var customerRepository = new CustomerRepository(provider);<br /><br />var controllerFactory = new ControllerFactory();<br /><br />controllerFactory.Register<HomeController>(() => new HomeController(customerRepository));<br /></tt><br /><br />When a request comes in to the ControllerFactory it can say something like:<br /><br /><tt><br />Dictionary<Type, Func<Controller> _controllerDictionary;<br /><br />...<br /><br /> _controllerDictionary[controllerTypeToBuild]()<br /></tt><br /><br />The syntax might look a bit weird, but essentially the dictionary contains functions which build a particular type. So when we grab something from the dictionary we just have to execute it hence the () call.<br /><br />No container, no builder classes. Just everything wired up ready to go in my application start-up.<br /><br />That might pose an architectural question of 'What do you mean by wiring up your application at start-up?' To answer than let me link you to <a href="http://misko.hevery.com/2008/08/21/where-have-all-the-singletons-gone/">Misko Hevery's</a> blog - a google guy with some awesome posts on writing testable applications.Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com3tag:blogger.com,1999:blog-12645766.post-17668530854972672962009-01-11T16:20:00.003+09:002009-01-11T16:55:34.221+09:00Learning OLAP and AnalysisAs a consultant I find myself working on different Customer sites doing a wide variety of different types of IT work. This might include Asp.Net, WPF, WCF, you name it, from the MS Technology Stack.<br /><br />One technology I'll be working with over the next few months is OLAP. It's a technology that I've always seen as slightly Voodoo-ish, Black Magic like, akin to walking into a mysterious smoky room with a pointy bearded Wizard lurking over a Crystal Ball!<br /><br />Over my next few blog posts I'll aim to break down some of the mystery and offer some laymans descriptions to OLAP - what it is, how it works, and how to work with it. For my first post I'll describe some of the key terms, along with some links that I've found useful on understanding it better.<br /><br /><span style="font-weight:bold;">Measure</span><br />This one is pretty simple. Whenever we analyse some data we are analysing a particular type of information. It's usually a numerical piece of data and some examples might be Sales Amount or margin, GST, VAT, etc.<br /><br /><span style="font-weight:bold;">Dimension</span><br />Starting with an example, lets I have some Sales Data against time. The total amount taken be a store per day. In this case my dimension is time! Simple huh? I might ask my OLAP database to show me the sales total against Time.<br /><br />As another example my sales data might also be broken down against location. I can ask my OLAP database to show me sales data for 2004 in Australia. We've defined another dimension, location.<br /><br /><span style="font-weight:bold;">Cube</span><br />No more black magic. Think of a cube - it's a simple 3-dimensional object. Lets say I have a cube where the X-dimension are my 'measures' - sales amount, margin, units sold, etc, my Y-dimension is time, and my Z-dimension is location.<br /><br />You should start to see how we can form a query to the cube along the lines of "Show me the total margin, in February 2008, in Western Australia". The Performance Point video I'll link to shows this beautifully, but take the cube and take the 'Slice' of the cube representing Margin. Then cut another slice of the same cube and get the WA slice. Finally cut a 3rd slice along the time dimension for 'February 2008'. What you'll end up with is one piece of the cube where these 3 slices intersect which happens to contain the data we're after. Simple huh?!<br /><br />Enough for now. Next time we'll either look into more detail around the Cube, or take a look at some of the query language (MDX) we use to write the queries to it.<br /><br /><a href="http://www.microsoft.com/business/performancepoint/productinfo/proclarity/training/WEB50P-1/OLAP_Terminology/OLAP_Terminology.html">Nice MS video on cube basics</a> <br /><br /><a href="http://en.wikipedia.org/wiki/OLAP_cube">Wikipedia on OLAP</a><br /><br /><a href="http://pagesperso-orange.fr/bernard.lupin/english/">Nice introduction linked from Wikipedia</a><br /><br /><span style="font-style:italic;">Updated 4:55pm removed the Slicing and Dicing quote. Not sure if that's what slicing and dicing is!!</span>Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-33094683158737400362008-12-17T09:50:00.002+09:002008-12-17T09:54:25.423+09:00Refactoring Asp.Net sitesI'm 1/2 way through refactoring an Asp.Net MVC site to use the new beta and noticed my solution compiling without any issues, but Asp.Net compilation errors appearing on run.<br /><br />Visual Studio wasn't compiling the content of the asp.net pages. Instead they were compiled on demand. Nothing wrong there... Unless you do a big refactoring and need to find errors on those pages all up-front.<br /><br />That's where the aspnet_compiler command line tool can come in and help. Basically it pre-compiles all pages in an asp.net application. I think the main reason is for performance reasons on a live environment, but it's fabulous for doing refactorings.<br /><br />aspnet_compiler -p. -v /<br /><br />executed from the root folder of your website will detect all errors in the markup.<br /><br />Enjoy!Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-32220011599016787862008-10-25T07:21:00.003+08:002008-10-25T07:58:17.704+08:00New things to learn... everywhere!If you don't like learning new things then I really wouldn't recommend working at Readify! If you do, then it will really invigorate you.<br /><br />Since starting here is a quick selection of some of what I've done<br /><ul><br /><li>Shadowed a TFS MVP on engagements soaking up as much TFS goodness as possible</li><br /><li>Installated TFS and showed customers how to use it</li><br /><li>Presented modules on a .Net 3.5 course that was run by Paul Stovell</li><br /><li>Architecture reviews / re-design</li><br /><li>Ran a 2 day workshop on Sql Server Reporting Services</li><br /><li>Presented a session at one of our free community events on WCF</li><br /><li>Produced a WPF Proof of Concept for a customer</li><br /></ul><br />In the next month I'll be presenting the .Net 3.5 course, running a 2 day WCF workshop, and getting my hands dirty with some Silverlight. <span style="font-weight:bold;">And</span> if all goes to plan I'll be going on a SCRUM Master course. <br /><br />SCRUM / agile methodologies have interested me since back in 2004 when my friend in the UK hired me to work on a SCRUM project at a big Investment Bank. The concepts really made sense to me in a ,"yeah - I knew something wasn't right on a lot of projects I worked on, but couldn't place why", way.<br /><br />Going forward with Readify I'm hoping to be doing more of the same around training, building, but also moving towards introducing agile approaches to customers that want to adopt them.<br /><br />Oh, and just because I mention the work SCRUM a lot, don't think I'm going to get into rugby.Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-16943958660177778532008-10-03T14:49:00.002+08:002008-10-03T15:30:46.565+08:00PrismI spent 1 1/2 years working on a large CAB application for a local Bank and was left with a bitter taste by CAB...<br /><br />Primarily because it was such a confusing framework to use. Developers found it really difficult to grasp WorkItems and we overused loosely coupled events almost using them to control our process flow.<br /><br />ObjectBuilder... Say no more.<br /><br />The guidance / reference implementations were, hmm, not great. They rendered their own views un-testable by having links to concrete classes which would instantiate views, generally breaking the whole idea of a testable design.<br /><br />So it's been with a little bit of fear that I downloaded the Prism guidance to have a look at what the WPF Composite Guidance is like. <br /><br />First impressions have been really pleasant. Yes I have seen ObjectBuilder2 (sounds like some dodgy horror movie title), but thankfully have been pretty shielded from it.<br /><br />WorkItems are gone - this is awesome. They were really unpleasant to explain to people.<br />DI has taken over bigstyle. Register everything with the Container, and things get resolved automatically. I was a little bit worried that I'd be swimming through Xml soup but smartly the IoC configuration is done in code at a module level.<br /><br />Things generally seem neater and cleaner. I got my 1st Application up and running in 30 minutes or so, compared to a few hours with CAB.<br /><br />So generally I'm pretty pleased. Add to that there is a Silverlight version. Cool! I'm sure I'll become a regular contributor to the Prism forums!Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-59241858509224750912008-10-03T14:45:00.002+08:002008-10-03T14:48:24.460+08:00Messing around with Conchango's SCRUM template for TFSI've spent a bit of time recently using TFS and trying to get my head around its templates.<br /><br />Out of the box you get one for MSF for Agile, and one for a heavier, CMMI process. Over the last couple of days though I've installed the Conchango SCRUM template and have been playing with it.<br /><br />So-far I'm pretty impressed. Especially with the online guidance. I think the videos of Ken Schwaber talking through the various phases of SCRUM are excellent.<br /><br />I worked with Version-One and Perforce in London a few years ago with great success so am looking forward to playing more with TFS / SCRUM.Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-9731994089635261462008-09-21T11:37:00.002+08:002008-09-21T11:41:18.586+08:00Installing TFS 2008 SP1I had the fun of doing a TFS installation on a customer site this week using TFS 2008 SP1 and Sql 2008.<br /><br />What fun! We ended up backing out the SQL 2008 installation, creating a new differencing disk from the Windows Server 2008 baseline we had, and putting SQL 2005 SP2 on instead. I'm not sure exactly what went wrong but the TFS Service just could not connect to the Tfs Warehouse database.<br /><br />Even with the SQL2K5 installation we had problems connecting through to the Reports from Team Explorer. What could save someone some time is this... Be sure to upgrade not only TFS to SP1 on the Team Explorer machine, but also VS2008. We only did VS2008 and obviously Team Explorer had changed as-well.Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-65222614823466399902008-08-15T11:49:00.001+08:002008-08-15T11:49:55.959+08:00RDN last nightThanks to everyone that came to the RDN last night, and to Chris for doing the "In-Depth" session.<br /><br />I defintely picked some good information up around Windows Workflow, and hopefully some of you got something out of my WCF Primer presentation. That was my 2nd presentation (I did one for the local .Net user group last year on the Composite Application Block).<br /><br />I was pretty nervous before, and for the 1st 5 minutes or so, but once I settled into it I managed to put my nerves to the side and present! It's challenging presenting to so many people when everyone is at a different level.<br /><br />One great thing from doing the presentation is that you learn things about the technologies that you might not have known about before. For example I understand the internals of WCF - its extensibility and messaging layer - much more than a week ago, and a lot of the terms I'd read about - behaviours for example - are a lot clearer in my mind!<br /><br />As for the experience, it's a buzz and I'd recommend it to anyone. I think it's awesome for building up confidence. I'm hoping to improve my skills as-well as time goes by and will use last night as a personal bench-mark. <br /><br />An interesting thing after last nights was looking through the feedback forms. I really appreciate the ones with the comments, and the lower scores as those are ones which are really useful for getting better. Not that I don't like the high scores - they are great too!!!<br /><br />So more coming soon hopefully. Watch this space!Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-23013306807935383282008-08-15T11:41:00.000+08:002008-08-15T11:42:02.282+08:00New job, new times, new challenges...It's been a while since I last wrote so here's an update of what I've been upto.<br /><br />I left the Bank I was working at. The politics were getting me down and it was wayyyy to stressful. I learnt tons of good stuff whilst there - .Net 3.0, WCF, WPF, CAB to name a few, and made some good friends as-well.<br /><br />I had a holiday to Vietnam and Cambodia which was awesome. Plenty of pictures at www.flickr.com/photos/graemefoster.<br /><br />And finally I started working for Readify, an MS Consultancy. For those in the UK who haven't heard of Readify they are a very well respected MS consultancy firm in Australia with a whole bunch of MVP's working for them. <br /><br />The job is going to be really challenging and exciting. I'll be consulting on architectures, running training sessions, giving presentations to the local community, fixing bugs for customers, you name it I'll be doing it!!!<br /><br />And along the way I hope to be writing more blog posts about, ummm, stuff!!!Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-11209785749454675822008-05-01T10:49:00.005+08:002008-12-10T02:11:15.457+09:00Excited by technology again!I'm a bit late jumping on this one but today I took delivery of my Squeezebox.<br />And I love it!<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe-PESupxM60pfVsgdsPk5v424Z5dfuM_6_hQ-pLWCGQn7WjM5QhJ91hgtFm3QSLLfr6U1GXNEFh3oh73H3y6_OCD32L_YK0n_zQC_xVzcpp6KpcKc_6mP557e_Y3RY9Wnj2o-/s1600-h/DSC_0002.JPG"><img style="cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe-PESupxM60pfVsgdsPk5v424Z5dfuM_6_hQ-pLWCGQn7WjM5QhJ91hgtFm3QSLLfr6U1GXNEFh3oh73H3y6_OCD32L_YK0n_zQC_xVzcpp6KpcKc_6mP557e_Y3RY9Wnj2o-/s320/DSC_0002.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5195237897439346962" /></a><br /><br />You can tell these guys have learned a thing or two from Apple on design.<br /><br />The box screams apple,<br />The setup experience was flawless. It just worked! <br /><br />Where are you?<br />Which wireless network?<br />Password?<br />It went and got an IP address.<br />Then updated its firmware.<br />Then hunted for the Slimserver server which I'd already installed on my Macbook. It just found it!!<br /><br />And now I can listen to XFM without having to lug my computer to the stereo!Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com1tag:blogger.com,1999:blog-12645766.post-70669928282860551052008-03-02T21:56:00.003+09:002008-03-02T22:02:46.906+09:00Choosing a technology for an applicationThe more work I do around WPF "smart" clients the less I believe they are the future. Maybe it's because I'm working on an application that I truly believe is using the wrong technologies and should be an asp.net application but I miss the freedom I felt writing web apps.<br /><br />I know there are a bunch of reasons for writing smart-client - offline, being one of them, but I think that reason is starting to look a little shaky given Google Gears... Now if Silverlight lets you run Sql CE (or equivalent) on the client I see that as one more reason not to write chunky fat clients.Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-13300099910208679752008-03-02T21:46:00.002+09:002008-03-02T21:56:08.529+09:00Using Uri's in CABRecently I was thinking about a neat addition to CAB that would allow a user to use a Url to "deep-link" into a CAB application (CAB as that's the technology I use at work).<br /><br />The way I see it working would be:<br /><br />Use a pluggable protocol to register my application with explorer.<br />Create a common url syntax to link a Uri to a Cab event<br />When the application starts follow one of two paths:<br /><br />1. If not already running then start up and pass the Url to the Url launcher service.<br />2. If not already running then open an ipc channel listening locally on port whatever<br />3. If already running then connect to the ipc channel and supply the url.<br /><br />Originally I thought that you could use the uri to directly create a CAB work-item. This is impossible to do right though. You don't know where the work-item should live in the hierarchy, if it is single instancing or multiple, or any number of contextual issues. Using a Cab event is bullet-proof though. Raise it globally and the subscriber can choose exactly what they want to do with it.<br /><br />Nice.Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-59536256658043161652008-02-25T20:48:00.001+09:002008-02-25T20:49:03.782+09:00Blog reactivatedWahay,<br /><br />For some reason my blog was deactivated when I checked it last week. Seems like Google have re-activated it!Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-30025405332252319582007-05-27T21:43:00.000+08:002007-05-28T21:39:55.580+08:00CAB, SCSF TestabilityI came across a class the other week called TestableRootWorkItem. I was put onto it from a post I made on the Smart Client forum, and it can be found in the Appraisal Work Bench test module.<br /><br />Basically it's a WorkItem which is initialised with a core set of services (of your choosing) and can then be used to test your own CAB code.<br /><br />Example time - imagine you've a presenter / view combo called ShowCustomersPresenter.<br />The view implements an interface called IShowCustomersView.<br /><br />In your test fixture you can use the TestableRootWorkItem a little bit like this:<br /><br /><tt><br />public void MyTestOfWhatever()<br />{<br /> TestableRootWorkItem rootItem = new TestableRootWorkItem();<br /> rootItem.Services.AddNew<ICustomerService, MockCustomerService>();<br /> ShowCustomersPresenter presenter = rootItem.Items.AddNew<ShowCustomersPresenter>();<br /> IShowCustomerView mockView = new MockView();<br /> presenter.View = mockView;<br /> presenter.FindCustomers();<br /> Assert.AreEqual(3, mockView.CustomerCount);<br />}<br /></tt><br /><br />so, what's going on here then?<br /><br />Well, we start with adding a mock customer service to the work item.<br /><br />Next we add an instance of the Presenter we want to test. ObjectBuilder will spot a [ServiceDependency] attribute looking for a service of type ICustomerService and will add my MockCustomerService which has been registered.<br /><br />The presenter's view is an IShowCustomerView. I don't want to test the real one so have added a MockView class which implements the interface. I have total control over this, but most importantly <span style="font-weight:bold;">it's not a UI component</span>.<br /><br />here is my implementation of these 2 classes:<br /><br /><tt><br />public class MockCustomerService: ICustomerService<br />{<br /> public IList<CustomerSearchResult> FindCustomers(string customerName)<br /> {<br /> return new List<CustomerSearchResult>(new CustomerSearchResult[] { ... });<br /> }<br />}<br /><br />public class MockView: IShowCustomerView<br />{<br /> public int CustomerCount = 0;<br /> public ShowCustomers(IList<CustomerSearchResult> results)<br /> {<br /> CustomerCount = results.Count;<br /> }<br />}<br /></tt><br /><br />it's pretty plain sailing from here.<br />I simulate someone clicking the Find button by calling presenter.FindCustomers() directly. <br /><br />My implementation of the Presenter under the hood calls the ICustomerService service to get the customers, and then calls View.ShowCustomers(results).<br /><br />Using a well known service, and a mock view I can prove in the test that indeed this is what is happening.<br /><br />To make it more interesting it's pretty straight forward to test Presenters raising or subscribing to events. You can create a MockEventSubscriber class which uses a CAB [EventSubscription(....)] to check for the raising of an event. The test method just has to add this class directly to the WorkItem (WorkItem.Items.AddNew<MockEventSubscriber>()) and you're there!<br /><br />CABs loose coupling event plumbing makes it perfect for writing classes that can be tested in isolation. In-fact, I think that if you're not testing CAB code in this way that you're really missing a trick! I'm about to start on the next phase of a CAB project and hope to report back on how it all goes!<br /><br />That's all for now :o)Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-76967746797055958092007-05-06T08:46:00.000+08:002007-05-09T21:00:00.065+08:00CAB / Smart Client Software Factory pointersI've been involved in a project which is using Microsofts Component Application Block for a few months now and thought I'd drop an entry on CAB 101 - do's and donots!<br /><br />CAB is heavily based around MVP and the idea of splitting use-cases into a WorkItem. Sounds complicated? Don't let it. A WorkItem is nothing more than a container of things which are required to get the job of a use-case done.<br /><br />So, a workitem may contain some views, some services, and some logic for co-ordinating them together. Simple huh?<br /><br />Lets look at a use case of searching for customers.<br /><br />What views are involved in this? For this example lets say we have a view to enter search text, and a view to show a list of customers.<br /><br />Get your GUI guys to knock up these 2 views. Make them look blinding! Just hold off on the actual guts of what is going on as it's not their job!<br /><br />GUI guys working on the views? Great. Let's begin the meaty stuff.<br /><br />Lets create a class that will hold all of the parts involved in the use-case together. This is will be subclass of WorkItemController.<br /><br />Override the Run() method on this type. Lets have it create a Search Criteria view and add it as SmartParts to the WorkItem's SmartPart collection.<br /><br /><tt>SearchCriteriaView view = WorkItem.SmartParts.AddNew<SearchCriteriaView>();</tt><br /><br />Let's also show this view in the main workspace.<br /><tt>WorkItem.Workspaces[MainWorkspace].Show(view);</tt><br /><br />Assume that the view has some fields for entering search criteria, and a Search button. When the user clicks on the Search button we'll delegate to our SearchCriteriaViewPresenter class (remember MVP)...<br /><br />The Presenter for the Search Criteria screen is the thing that will go and find the results. But how does it do this? <br /><br />This is where we use another piece of CAB goodness - its DependencyInjection framework. CAB will wire up objects we want, setting properties on them by magic. Did I mention that we have already asked CAB to register a CustomerSearch service on our behalf? Nope? Well we did! <br /><br />In the Search Criteria presenter we'll have some lines that look like this...<br /><br /><tt><br />[ServiceDependency]<br />public ICustomerSearch<br />{<br /> set { _customerSearch = value; }<br />}<br /><br />public void Search(....)<br />{<br /> IList<SearchViewCustomer> customers = _customerSearch.Search(....)<br />}<br /></tt><br /><br />But how do we get these results to the results view? This is where CAB's idea of loose coupling comes into play. What we'll do is add the results into the WorkItem's Items Collection and then raise an event to say we've found some search results. The Search method becomes more like this.<br /><br /><tt><br />[EventPublication("ResultsReturned", PublicationScope.WorkItem)]<br />public event EventHandler<EventArgs> ResultsReturned;<br /><br />public void Search(....)<br />{<br /> IList<SearchViewCustomer> customers = _customerSearch.Search(....)<br /> WorkItem.Items.Add(customers, "CustomerList");<br /> ResultsReturned(this, EventArgs.Empty);<br />}<br /></tt><br /><br />Woah! What's going on there. Well the EventPublication line instructs CAB that this class can raise a CAB event. CAB events offer more flexibility over .net events. We can change the scope of who they are raised to. In our case we're going to tell the WorkItem that we've found some results.<br /><br />Go back to the WorkItemController from earlier and add the following method.<br /><br /><tt><br />[EventSubscription("ResultsReturned")]<br />public void OnResultsReturned(object sender, EventArgs e)<br />{<br /> ResultsView view = WorkItem.SmartParts.AddNew<ResultsView>();<br /> WorkItem.Workspaces["MainWindow"].Show(view);<br />}<br /></tt><br /><br />Remember that other gui screen that was being prepared? Get into the Presenter and add a constructor.<br /><br /><tt><br />[InjectionConstructor]<br />public ResultsViewPresenter(<br /> [ComponentDependency("CustomerList") IList<Customer> customers] )<br />{<br /> View.Customers = customers;<br />}<br /></tt><br /><br />The InjectionConstructor attribute is a Object Builder attribute that will let us easily inject data into the new Presenter. In this case we are telling builder that the constructor is dependent on an item called CustomerList. It will look for this item in the Items collection and pass it to the constructor for us.<br /><br />All we have to do is bind the customers list to the view. <br /><br />Recap! What have we achieved?<br /><br />We've created 2 smart parts which act together to perform the use case of finding customers. <br />W've created a WorkItemController which will hold these 2 views giving us a context for working with just the 2 views loosely without them knowing about each other.<br />We've used a CAB Event to tell anyone interested that we found some customers.<br />We used CAB's Items collection to share the customers between 2 views without either of them being aware of each other.<br />And we used the dependency injection system to obtain a reference to a service, and to wire up a Presenter.<br /><br />Not bad for 10 minutes work!Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com1tag:blogger.com,1999:blog-12645766.post-31779926493907316562007-05-06T08:44:00.000+08:002007-05-06T08:46:25.622+08:00So long England, hello Australia!Well it's been a while since I last wrote a blog entry but I have decided to start up again for no particular reason!<br /><br />I'll probably keep it quite techie this time though. I'm currently working on a WPF / CAB project so I might drop some entries from time to time about these technologies.Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0tag:blogger.com,1999:blog-12645766.post-1125059608821974152005-08-26T20:18:00.001+08:002008-03-17T15:58:24.216+09:00What part of cancelled don't you understandJust over two weeks ago my wife had the misfortune of having her wallet stolen which contained a bit of cash and a debit card.<br /><br />It wasn't long before she noticed and I called the bank for her to cancel the debit card. I walked through the transactions which had occurred that day, all which were bona-fide attributed to her, and the card was duly cancelled.<br /><br />It was a bit disturbing to find last night £1300 of transactions, dated a week later, for train tickets (GNER, Virgin) from Euston station each for £280 - £350 (now that's a HELL of a lot of money for one train ticket but 1st class can be that expensive in the UK).<br /><br /><ul> <li>Interestin point 1 - the account was close to zero when the card was stolen and had a £500 overdraft. How come £1300 of transactions was </li> <ul> <li>allowed<br /> </li> <li>didn't register as a strange spending pattern even though said bank claims to have state of the art transaction pattern monitoring systems.<br /> </li> </ul> </ul><br />So being very, very alarmed my wife phoned up the bank (a big global world bank who shall rename nameless) and was routed to the call centre in some other country in the world. She was told that the transactions had occurred the night the card was stolen, and most likely in the window between it being stolen and being cancelled. Alarm bells started ringing - am I protected, will I be re-imbursed for what is a months salary, etc, but she were told nothing could be done that night and se'd have to call customer service the next morning.<br /><br />So, 8am and the call to customer service. Again, nothing could be done but the transactions had been authorised on the Friday night when the card was stolen. She was bounced to the fraud department. Here's where things started getting ridiculous:<br /><ul> <li>The fraud department couldn't help and suggested she went into a branch. Now call me stupid but isn't a fraud department supposed to deal with fraud.</li> <li>Ridiculous suggestion 1: Said bank offered to increase her overdraft to help her get through the month. Great idea - not content with letting someone spend £1300 from an account with a £500 overdraft they now want to push the limit up so she can bring her account even more into the red.</li> </ul> So, 10am and my wife visits the branch. I will stress that the staff in the branch were very helpful - is this an argument against outsourcing. It's much harder for someone un-connected in some random bit of the globe to emphasise with the situation.<br /><br />Aside from that, here is the bit I love most of all -<br />The transactions that occurred on the Friday night occurred at 9:30pm. But how can that be? The card was registered stolen at 8:30pm. Well here is the icing on the cake.<br /><br /><ul> <li>EACH TRANSACTION WAS MARKED WITH "INCORRECT ISSUE NUMBER ON CARD"</li> </ul> <ul> <ul> <li>A card is stolen, registered as stolen, but then £1300 of transactions are allowed even though the system at some point knows that this card is not supposed to be used.</li> </ul> </ul> I'm glad this has shown up next to the transactions as it proves that the card was cancelled. I'm gobsmacked that the transactions were authorised even though the card had been cancelled.<br /><br />Am I surprised credit / debit card fraud is massively increaing???? Not on your life. If registering a card as stolen doesn't actually stop it being used then what chance is there of this sort of fraud being stopped?Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.comtag:blogger.com,1999:blog-12645766.post-1118751329270442542005-06-14T20:12:00.000+08:002005-06-14T20:15:29.273+08:00Live 8 & EbayHmm, did nobody envisage this happening?<br /><br />I've been speculating since the tkx were announced that there would be a flood of people trying to sell their tickets on eBay as soon as they got them!<br /><br />That's just the state of the world we live in today. Too many people who want to make a quick buck for doing nothing at-all.<br /><br />Sorry Bob, cry all you like but maybe you should have learned the Glastonbury lesson which is to print security into the tickets and make sure whoevers name is on, is at the gate.<br /><br />(For the record I think it's a terrible situation that people are doing this, and if I had a pair I wouldn't think of it. It's my 30th birthday tho' so I'm having a party instead!!)Graeme Fosterhttp://www.blogger.com/profile/13954998731202074497noreply@blogger.com0