C#, Amazon Web Service AWS, SES, Bulk Email »

[4 Dec 2011 | 0 Comments]

I recently did a talk at DevEvening about how I managed to using Amazon’s Simple Email Service with my (fairly) new website The Gig Market and I thought I would just share a bit more information about it if anyone was interested.

The Problem

As the website is hosted on Windows Azure there is no hosting mail server that I can use to send out emails. The answer is to use a 3rd Party service to do this for you. I had been using a company for 3 years for my other websites to do this and had been very happy with them…. until I breached the send limit one month and they  just stopped sending emails. This really annoyed me so I set about to find a better service. What I found was AWS’s SES which only costs $0.10 per 1000 emails, the problem was it is a webservice, not an smtp server, so I couldn’t just change the smtp server in my app’s settings.

The Research

What I wanted to do was to tweak my code to use SES api. To limit the impact I only wanted to change the:

SmtpClient smtp = new SmtpClient();
smtp.Send(mailMessage);

code to something that could just send the mailMessage object to Amazon SES. The problem is that out of the box the .Net MailMessage object can only be used with the .Net SmtpClient. doh.

I found a couple of other people with the same idea:

http://www.codeproject.com/KB/IP/smtpclientext.aspx

This post by Allan Eagle was a great start for me as it showed me how to get at the guts of the mail message object by using reflection. Now I only had to  send it to SES right?

http://neildeadman.wordpress.com/2011/02/01/amazon-simple-email-service-example-in-c-sendrawemail/

This post by Neil Deadman was a great article and I thought I had found my solution BUT there was a big big problem. I needed to send BCC and set the priority of the email. It turned out that I could not achieve this using the solution. So what could I do?

The Solution

I ended up hitting the Amazon docs and discovered that I would have to send a RAW message format and I would also have to write the email out by hand in MIME format. I thought this would be hard but it turned out to be pretty easy, I knocked up an extension method on the MailMessage class to do this for me.

public static string ToAmazonSesRawFormat(this MailMessage message)
        {
            var result = new StringBuilder();
            result.AppendLine("MIME-Version: 1.0");
            result.AppendLine(string.Format("From: {0}", message.From));

            if (message.To.Count > 0)
            {
                result.Append("To: ");
                int toMessageCount = 0;
                foreach (var address in message.To)
                {
                    result.Append(string.Format(
                        "{0}{1}",
                        toMessageCount == 0 ? string.Empty : ",",
                        address));

                    toMessageCount++;
                }    
            }
            
            if (message.CC.Count > 0)
            {
                result.AppendLine(string.Empty);
                result.Append("Cc: ");
                int ccMessageCount = 0;
                foreach (var address in message.CC)
                {
                    result.Append(string.Format(
                        "{0}{1}",
                        ccMessageCount == 0 ? string.Empty : ",",
                        address));

                    ccMessageCount++;
                }    
            }
            
            if (message.Bcc.Count > 0)
            {
                result.AppendLine(string.Empty);
                result.Append("Bcc: ");
                int bccMessageCount = 0;
                foreach (var address in message.Bcc)
                {
                    result.Append(string.Format(
                        "{0}{1}",
                        bccMessageCount == 0 ? string.Empty : ",",
                        address));

                    bccMessageCount++;
                }    
            }
            result.AppendLine(string.Empty);
            result.AppendLine("Subject: " + message.Subject);
            result.AppendLine(string.Format("Content-Type: {0}", message.IsBodyHtml ? "text/html;" : "text/plain;"));
            result.AppendLine(string.Format("Content-Transfer-Encoding: quoted-printable"));
             
            result.AppendLine(string.Format("X-Priority: {0}", ((int) message.Priority).ToString()));

            result.AppendLine(string.Empty);

            if (message.IsBodyHtml)
            {
                var encoder = new QuotedPrintableEncoder();
                result.AppendLine(encoder.EncodeFromString(message.Body, Encoding.ASCII));    
            } 
            else
            {
                result.AppendLine(message.Body);
            }
            
            return result.ToString();
        }

Now all I had to do was send the mesage via the SES RawMessage api:

AmazonSes.SendEmail.Instance.SendRawMessage(mailMessage);
 
The SendRawMessage function is a wrapper I put in the wrapper class I wrote for the API:
 
public void SendRawMessage(MailMessage mailMessage)
        {
            var memoryStream = new MemoryStream();
            using (memoryStream)
            {
                var encoding = new UTF8Encoding();
                var byteArray = encoding.GetBytes(mailMessage.ToAmazonSesRawFormat());

                memoryStream.Write(byteArray, 0, byteArray.Length);
                memoryStream.Position = 0;
                var message = new RawMessage(memoryStream);
                var sendRawMessageRequest = new SendRawEmailRequest(message);
                var response = Client.SendRawEmail(sendRawMessageRequest);
            }
            
            memoryStream.Close();
        }

Git »

[2 Jul 2011 | 0 Comments]

So I have been very busy this year and have not had time to blog anything. Now I find myself at the www.dev4good.net event and needing to show people on my team how to get the tools needed to use Git effectivly installed and running on their computers.

This post is just a short instruction set on how to do this and could be of use to others!

When I was trying to do this the following guide was so valuable:

http://www.paulrohde.com/github-101-on-windows/

Tools to download

http://git-scm.com/download <- install this first

http://code.google.com/p/tortoisegit/ <- install this second :)

»

[25 Feb 2011 | 0 Comments]

I was kindly given the opportunity to give a talk to the DevEvening crowd about my experiences with using PayPal’s Adaptive Payment services.

These Adaptive Payment services offer some very interesting and useful ways to collect and distribute money on the Internet, which is very important if you want to make a living with an online business!

My experience with the the Api was implementing a Chained Payment system on my Training Course Booker website to collect and distribute money to Training Providers that use it. There are lots of other uses, to find out more please visit PayPal’s developer website x.com and / or have a look at my slide deck below.

The video of me demoing training course booker at Le Web

C#, MS CRM, MS CRM4, Dynamics Crm »

[24 Jan 2011 | 0 Comments]

On my current Microsoft Dynamics Crm project we have done a lot of customisations, both creating custom pages and manipulating the existing crm pages via the OnLoad method. This post describes a method of ensuring the load order plus the benefit in increasing performance compared with loading multiple external JavaScript files the more conventional way.

The existing approach

One of the big problems we faced was making sure that the JavaScript files load in a specific order. This is because we have got some common functions in a file which can be re-used in multiple pages. These need to be loaded before the main page JavaScript file which might call one of the common functions.

There are a number of good blog post about this topic so I won’t go over this ground again. Here are a few articles I’ve found:

http://danielcai.blogspot.com/2010/02/another-talk-about-referencing-external.html
http://www.henrycordes.nl/post/2008/05/27/External-js-file-and-CRM.aspx

What is different with this new approach

The solution that I propose here was the brainchild of @njwatkins who came up with the idea of implementing at generic .net http handler as part of our custom webpages proejct that would read in the various external JavaScript files, in the correct order, compress them and then stream them back to the browsers as a single JavaScript file.

Unfortunately I cannot post the source code of the handler we use on this project here but a google round on topics like Gzip and StreadReaders and Handlers should enough to get most developers to a solution.

So the is script that goes on the onload of the Crm Enitty:

function loadJavaScript(file, onComplete) {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = file;
        if (onComplete) {
            script.onreadystatechange = function() {
            if (this.readyState == 'complete' || this.readyState == 'loaded') {
                onComplete();
            }
        }
    }
    document.getElementsByTagName('head')[0].appendChild(script); 
};

loadJavaScript('/ISV/Northwind/ExternalJavaScript/contact.ashx', function() { if (EntityFormOnLoad) { EntityFormOnLoad(); } });

The contact.ashx file is the handler that does all the work and where you would define which JavaScript files to include and does the merging and compressing. It means you only need to load one external JavaScript reference and you can guarantee which order they external files will be loaded.

Other benefits of this approach is that you can control things like caching length which can be a problem when changing and deploying new external files to clients. We achieved a significant saving on load time of the javascript from 900ms down to 200ms using this approach and we have ideas on how to improve it further but this is as far as we have got today!

»

[25 Nov 2010 | 0 Comments]

If you follow my blog you will hopefully be well aware of my involvement with the Windows Phone 7 development community in the UK. I was fortunate enough to be invited to the launch party of the phone in London as well as present demo’s of apps I’m developing to London’s Windows Phone User Group.

‘The short’ of the post is if you want to be compliant with Microsoft’s stying guidlines watch this video about some templates they have developed and made available for free download for Windows Phone Development. Please read to the end of the article for ‘'the long’ of my thoughts!

 

One of the things which is a building block of Microsoft’s vision of Windows Phone 7 (WP7) is a consistent feel to applications that are developed and put into Marketplace. This is why the developed Metro as well as spending a lot of time and energy into creating detailed design guidelines for developers to follow. The problem is the majority of developers are more interested in writing code that reading design documents, are more interested in getting async callbacks to work than making sure the pixel spacing is correct between their labels and textboxes. Unfortunately for techies spacing and nice looking UI is as important to you app as the technical solution (developers are just a cog) To help us coding slaves Microsoft have kindly developed some Blend templates that implement the UI design templates, these can be copy and pasted into your solution for free.

Windows Phone 7, WP7, Microsoft »

[26 Oct 2010 | 1 Comments]

imageSo this is not breaking news but I was lucky enough to be invited to the Developer Launch party held by Microsoft in central London. This was the real party for those who are really involved in making the phone happen and want to build apps for the phone not the party for those hangers on who were fobbed off with this party ;-)

I had a great time, met a load of interesting people doing interesting things for Windows Phone 7 and I managed to get a few sound bites of video from some of them which I have edited together for your viewing enjoyment!

 

My Windows Phone 7 Developer launch party experience!

 

Many thanks to @will_coleman and his team for making everything happen and I am really looking forward to the future!

»

[13 Oct 2010 | 0 Comments]

I’ve just discovered something that I really really don’t like about Microsoft CRM 4. This is that creating some custom workflow activities that are used in a Crm Workflow means they are linked together forever and ever by version numbers.

I was getting this error message:

custom-workflow-step-is-not-valid

After some investigation it turned out that it was because I had changed the version number of the assembly that contained the custom workflow activities which meant that I could no longer publish the workflows that use them. When I try I get this error message.

The answer is to manually set the version number of the dll back to what it was when the workflows were originally published which is just silly.

For a much more detailed look at this problem I found this fantastic article by Eric Bewley.

Software Developement »

[7 Oct 2010 | 0 Comments]

We have recently upgraded our development environments on my project to match the production environment which is running on a 64bit servers. There was a big gotcha which was the delayed signed dll’s in the dev environment were chucking a “Strong name validation failed” error when they were accessed.

There are well documented solutions around using the following command

SN.exe -Vr *,*

However this did not work on the 64bit computer because SN.exe is a 32bit program and put the entry in the 32bit part of the registry. So I moved the registry key this tool enters and put it in the 64bit part of the registry and then everything worked.

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\*,*]

Hope that helps some people out there ;)

charity, Windows Phone 7, programming, paypal, WP7, hacking »

[23 Sep 2010 | 3 Comments]

So I went to Charity Hack and as promised have put together a video of the event.

The Event

It was a great event (again) with the standard of apps even better than last year. John Lunn has done a write up of the event with videos of all the winning hacks.

There is also a great write up by Ben Matthews about all 18 entries which is well worth a read to get a overall feel of the event. http://benrmatthews.posterous.com/28520434

There is also a great photo stream here of the event: http://www.flickr.com/photos/martin_88/with/5004083392/

Our App

We created a Windows Phone 7 app which used a number of API’s provided by JustGiving and PayPal to collect the donations from users. We only had a limited time to learn what the development tools for Windows Phone 7 could do but it was really easy to pickup and get something doing pretty complex api calls in a very short time. It does an number of restful web service calls in the background which was made even easier with the http://restsharp.org/ library. We were really pleased with the outcome so please enjoy the video!

MS CRM4, MS CRM, C#, programming, Software Developement »

[17 Sep 2010 | 0 Comments]

Now this might seem like something that would be easy to do but I’ve just spent 2 days struggling to do just this because of what I consider a bug in one of the SDK wrappers. I have now found a work around to enable unit testing which I will share with you now.

The Error message

Test method XrmEntityWrappers.Tests.CaseEntity.GetCaseByTicketNumber threw exception:  System.TypeInitializationException: The type initializer for 'Microsoft.Xrm.Client.Caching.Cache' threw an exception. --->  System.IO.DirectoryNotFoundException: Could not find a part of the path 'appDomain=UnitTestAdapterDomain_ForC:\Projects\Thg.Ohov.Crm\SourceCode\Thg.Ohov.Crm\TestResults\dh27_WIN-51UPWVCUQ6V 2010-09-16 18_21_40\Out\XrmEntityWrappers.Tests.dll:key=Microsoft.Xrm.Client.Caching.InMemoryCacheProvider'..

System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
b__0(Object userData)
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
System.Threading.Mutex..ctor(Boolean initiallyOwned, String name, Boolean& createdNew, MutexSecurity mutexSecurity)
System.Threading.Mutex..ctor(Boolean initiallyOwned, String name)
Microsoft.Xrm.Client.Threading.MutexExtensions.Lock(String key, Int32 millisecondsTimeout, Action`1 action)
Microsoft.Xrm.Client.Threading.MutexExtensions.Get[T](String key, Int32 millisecondsTimeout, Func`2 loadFromCache, Func`2 loadFromService)
Microsoft.Xrm.Client.Threading.MutexExtensions.Get[T](String key, Int32 millisecondsTimeout, Func`2 loadFromCache, Func`2 loadFromService, Action`2 addToCache)
Microsoft.Xrm.Client.Threading.MutexExtensions.Get[T](String key, Func`2 loadFromCache, Func`2 loadFromService, Action`2 addToCache)
Microsoft.Xrm.Client.Caching.InMemoryCacheProvider.GetExtendedCache()
Microsoft.Xrm.Client.Caching.CacheManager.GetExtendedCache()
Microsoft.Xrm.Client.Caching.Cache..cctor()
Microsoft.Xrm.Client.Caching.Cache.Get[T](String label, Func`2 load)
Microsoft.Xrm.Client.CrmConnection..ctor(String connectionStringName, String connectionString)
Microsoft.Xrm.Client.CrmConnection.Parse(String connectionString)
Thg.Ohov.Crm.Core.XrmEntityWrappers.XrmAdapter..ctor() in C:\Projects\Thg.Ohov.Crm\SourceCode\Thg.Ohov.Crm\Core\XrmEntityWrappers\XrmAdapter.cs: line 28
Thg.Ohov.Crm.Core.XrmEntityWrappers.incident.get_XrmAdapter() in C:\Projects\Thg.Ohov.Crm\SourceCode\Thg.Ohov.Crm\Core\XrmEntityWrappers\incident.cs: line 25
Thg.Ohov.Crm.Core.XrmEntityWrappers.incident.GetIncident(String caseId) in C:\Projects\Thg.Ohov.Crm\SourceCode\Thg.Ohov.Crm\Core\XrmEntityWrappers\incident.cs: line 44
XrmEntityWrappers.Tests.CaseEntity.GetCaseByTicketNumber() in C:\Projects\Thg.Ohov.Crm\SourceCode\Thg.Ohov.Crm\XrmEntityWrappers.Tests\CaseEntity.cs: line 23

The reason for the error

The Microsoft.Xrm.Client.dll tries to create a Mutex object with the

Thread.GetDomain().FriendlyName;

When running ordinary in a console app or web app this is not a problem as the FriendlyName does not contain any ‘\’ characters. However UnitTest frameworks do put ‘\’ characters in the GetDomain().FriendlyName which then causes the Mutex object to throw a ‘System.IO.DirectoryNotFoundException’.

The fix

The real fix is for Microsoft to update the Microsoft.Xrm.Client.dll so that it doesn’t put any ‘\’ characters into the Mutex constructor. However my work around for this is thanks to Nick Watkins who found this article on how to change the GetDomain().FriendlyName

http://www.timvasil.com/blog14/post/2008/11/Fixing-Instance-names-used-for-writing-to-custom-counters-must-be-127-characters-or-less.aspx

The key bit of code being this if you want to set the FriendlyName to ‘Test’ (which doesn’t have any ‘\’ characters!):

typeof(AppDomain).GetMethod("nSetupFriendlyName", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(AppDomain.CurrentDomain, new object[] { "Test" });

To rename the GetDomain().FriendlyName before calling any of the wrapper code in the unit tests. So the test might look a bit like this:

[TestMethod()]
        public void GetIncidentTest()
        {

typeof(AppDomain).GetMethod("nSetupFriendlyName", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(AppDomain.CurrentDomain, new object[] { "Test" });

            string caseId = "1234"; // TODO: Initialize to an appropriate value
            incident expected = null; // TODO: Initialize to an appropriate value
            incident actual;
            actual = incident.GetIncident(caseId);
            Assert.AreEqual(expected, actual);

}

Summary

I’m happy now I can unit test my custom code that uses the xRM Wrappers and I hope that my support call with Microsoft will result in the SDK dll being updated.