Easy Email Templates in .NET with FluentEmail

Filed Under (Email) by admin on 03-09-2010

Tagged Under : , , ,

I always seem to forget how to send emails in .NET which to me seems like such a simple task. Lately I’ve been working on updating an older application of mine that’s soul purpose was to read a database and send emails depending on certain events. I had a look at the current code and saw something like this:

sb.Append("A Transaction has been made...<br />");
sb.Append("<table><tr><th>Reservation Number</th><th>Customer Name</th><th>Email</th><th>Sale Date</th><th>Amount</th></tr>");
sb.AppendFormat("<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td></tr>",
    transaction.Reservation, transaction.FullName, transaction.Email, transaction.SaleDate, transaction.Amount.ToString("C2"));
sb.AppendFormat("<tr><th>Invoice</th><th>Confirmation</th></tr><tr><td>{0}</td><td>{1}</td></tr></table>", transaction.Invoice, transaction.Confirmation);

Terrible! So I figured while I was updating it I’d work out a better way build up the HTML of the emails. I started with the FluentEmail Project (Luke’s Post about it). From there I added some basic templating features, such as loading a HTML file with placeholders for content and the rest is history…

 

With my recent updated to FluentEmail I was about to turn something that looked like the above code to this: (as always C# is the code of choice)

//Send Email!
var email = Email
            .From(_fromEmail)
            .To(toAddresses)
            .Subject(string.Format("Siriusware Emailer Confirmation #{0}", transaction.Confirmation))
            .UsingTemplate(@"C:\Emailer\TransactionTemplate.htm")
            .Replace("<%Reservation%>", transaction.Reservation)
            .Replace("<%FullName%>", transaction.FullName)
            .Replace("<%SaleDate%>", transaction.SaleDate.ToShortDateString())
            .Replace("<%Amount%>", transaction.Amount.ToString("C2"))
            .Replace("<%Invoice%>", transaction.Invoice)
            .Replace("<%Confirmation%>", transaction.Confirmation)
            .UsingClient(new SmtpClient(_mailhost));
email.Send();

 

The HTML inside TransactionTemplate.htm has the below code. This is a basic example but demonstrates the usage of the templates.

<html>
<head>
    <title></title>
</head>
<body>
    A Transaction has been made...<br />
    <table>
        <tr>
            <th>Reservation Number</th>
            <th>Customer Name</th>
            <th>Email</th>
            <th>Sale Date</th>
            <th>Amount</th>
        </tr>
        <tr>
            <td><%Reservation%></td>
            <td><%FullName%></td>
            <td><%Email%></td>
            <td><%SaleDate%></td>
            <td><%Amount%></td>
        </tr>
        <tr>
            <th>Invoice</th>
            <th>Confirmation</th>
        </tr>
        <tr>
            <td><%Invoice%></td>
            <td><%Confirmation%></td>
        </tr>
    </table>
</body>
</html>

Pretty damn easy if you ask me.

This also give me the flexibility to edit the HTML file in a proper editor instead of concatenating all those strings together. The main idea was inspired by the MailDefinition class built into .NET but I didnt like the face that: 1 it was part of the System.Web.UI.WebControls namespace when its not a Web Control and wouldnt be used as one. And 2, It attempted to use another Control as a worker for it. So I just extended MailMessage to add the functionality.

All you need to do is download FluentEmail from Github

DroppedBoxx v1.1 – Dropbox for Windows Mobile

Filed Under (Mobile) by admin on 03-06-2010

Tagged Under : , ,

So I have been developing a Dropbox Client for Windows Mobile called DroppedBoxx and I thought I’d take some time to talk about how it works, my plans for its future and talk about some of the new features of the latest version v1.1 which has now been released to the Windows Phone Marketplace and Handango.

 

Firstly, the new features in v1.1 include: (Full Changelog)

  • Two-way Syncing of selected folders
  • Updated UI (Labeled buttons, Background Uploading, Sync Folders screen is updated so you know when its syncing)
  • Bug fixes for the Attach to Email and errors caused by loss of connection
  • Added settings for camera resolution

Login:ScreenShot2

This screen is where the User Logs in user their dropbox account. Login button trys to login, keyboard button shows the Windows Mobile SIP keyboard. Exit button exits the app. Remember me saves your login details so next time you run the app your automatically logged in.

 

Sync Folders/Home Screen:

This is pretty much the Home screen for the application. From here you can add folders for Syncing by clicking New and browsing the phones file system and selecting a Folder to add. The Logout button on the top right obviously logs you out returning to the login screen.

The 5 Buttons down the bottom:

  • The Sync button starts the “Sync” process syncing the folders in the list to your dropbox account into a folder called “Droppedboxx” (Note: this feature is unavailable in the Beta versions, more on that later)
  • The Dropbox Button opens up the root folder of dropbox for you to browse.
  • The settings button opens the settings screen where you can change app settings (such as Clearing saved login, max file sizes and camera resolution.
  • The Info button is to show the dropbox User info, including quota and usage but also DroppedBoxx version information and data used by this DroppedBoxx session.
  • The Exit button closes the app.

ScreenShot3

Browse Dropbox:

This is where most of the functionality is, from this screen we can upload, download, delete, etc. files from Dropbox. Starting at the top, the Back Button takes you “up” a directory in the Dropbox file system or, if your in the dropbox root, takes you back to the Home Screen. The Upload button lets you browse the phones file system and select a file to upload.

Here you have a list of Files and folders that are in the current folder on Dropbox selecting a folder opens up that folder.

The bottom button panel:

  • The Camera button opens up the Windows Mobile camera application and when you take a photo it uploads it to the folder you are currently in in the Dropbox browser.
  • The new folder button simply creates a new folder in the current folder, opening up a dialog to enter the Name.
  • The Delete folder button Deletes the current folder your in (asking for confirmation first)
  • The Paste button is for moving/copying files, if you have a file in the “clipboard” pressing this button will ask if you want to copy or move the file to this folder. (More info in file menu)
  • The Back Button goes back to the sync folders screen (The Back button on the top left goes up a directory or back to sync folders if your in the dropbox root)

ScreenShot4 The File Menu:

This is the menu that comes up after selecting a dropbox file.

  • Save Button Downloads the selected file (opening a file system browser to set the download folder)
  • Email button, downloads the file to a temp folder and attaches it to a New email message in Pocket Outlook (assuming this is set up it firsts asks you to select the account)
  • The Copy button puts the selected file in the “clipboard” so you can paste it somewhere else in the dropbox file system (giving you options to Copy or Move the file)
  • The bin button deletes the selected file (asking for confirmation first)
  • The –Menu button simply closes the file menu (to allow access to the Folder menu again)

Settings:ScreenShot10

Here you can change the Settings of the application such as clearing saved login details, setting a max filesize for sycning and setting the camera resolution for camera uploads.

Information:

This screen displays application and user info. It shows the DroppedBoxx version number and data sent and received by the application for this session. As well as the users dropbox quota information.

 

DroppedBoxx can be downloaded from the Windows Phone Marketplace or Handango.

Also you can follow the discussion about this app by going to the thread on XDA.

Dropbox API, RestSharp and C# Part 2: The Revenge!

Filed Under (Code) by admin on 25-05-2010

Tagged Under : , , ,

Following on from my previous post where I showed you how to Login and get the Account Info for a Dropbox account. Today we dive into the Box full of files. Uploading, Downloading and Deleting!

 

A lot has changed since my last post in the way of RestSharp with OAuth. OAuth is now available Out-of-the-box (this can be downloaded from Github). Ok, Time for some code…

Download File:

Update: Fixed a bug in the code that only allowed for text based files to be downloaded. Using restClient.DownloadData now instead of Execute to get the response’s raw Data.

public byte[] DownloadFile(string path)
{
    var restClient = new RestClient("http://api-content.dropbox.com");
    //load the JsonDeserializer for all types
    restClient.ClearHandlers();
    restClient.AddHandler("*", new JsonDeserializer());
    if (!path.StartsWith("/")) path = "/" + path;

    restClient.Authenticator = new OAuthAuthenticator(restClient.BaseUrl, _apiKey, _appsecret, _userLogin.Token, _userLogin.Secret);

    var request = new RestRequest(Method.GET);
    request.Resource = "{version}/files/dropbox{path}";
    request.AddParameter("version", _version, ParameterType.UrlSegment);
    request.AddParameter("path", path, ParameterType.UrlSegment);

    var responseData = restClient.DownloadData(request);

    return responseData;
}

Note: This is assuming the user has already logged in and we have the token/secret (_userLogin).

Starting from the top, we create a new Instance of the RestSharp Client with the baseUrl then set the Json Deserializer for all requests. We then set the RestClient’s Authenticator to the OAuthAuthenticator and give it our baseUrl, all our secrets and that is all we need to do for OAuth (the rest is build into RestSharp, awesome?!). Now we create the Request up, its a GET method, set the version and path of the file to download call Execute and you have just downloaded your first Dropbox API file! I then converted this to a stream so save back to a local file.

Delete File:

public bool DeleteFile(string path)
{
    var restClient = new RestClient("http://api.dropbox.com");
    //load the JsonDeserializer for all types
    restClient.ClearHandlers();
    restClient.AddHandler("*", new JsonDeserializer());

    if (!path.StartsWith("/")) path = "/" + path;

    restClient.Authenticator = new OAuthAuthenticator(_restClient.BaseUrl, _apiKey, _appsecret, _userLogin.Token, _userLogin.Secret);

    var request = new RestRequest(Method.GET);
    request.Resource = "{version}/fileops/delete";
    request.AddParameter("version", _version, ParameterType.UrlSegment);

    request.AddParameter("path", path);
    request.AddParameter("root", "dropbox");

    var response = restClient.Execute(request);

    return response.StatusCode == System.Net.HttpStatusCode.OK;
}

Delete is pretty similar to Download, only differences is the Url, the response and this time the path is sent as a parameter instead of part of the Url. The “root” parameter is for applications that only have sandbox access (they would set this to sandbox) who only get access to a “sandbox” folder on the users dropbox account.

Upload File:

Now this is where I had the most difficulties, many “Forbidden” messages later I finally came up with the solution!

public bool UploadFile(string path, FileInfo localFile)
{
    var restClient = new RestClient("http://api-content.dropbox.com");
    //load the JsonDeserializer for all types
    restClient.ClearHandlers();
    restClient.AddHandler("*", new JsonDeserializer());

    if (!path.StartsWith("/")) path = "/" + path;

    //Get the file stream
    byte[] bytes = null;
    FileStream fs = new FileStream(localFile.FullName, FileMode.Open, FileAccess.Read);
    BinaryReader br = new BinaryReader(fs);
    long numBytes = localFile.Length;
    bytes = br.ReadBytes((int)numBytes);

    restClient.Authenticator = new OAuthAuthenticator(_restClient.BaseUrl, _apiKey, _appsecret, _userLogin.Token, _userLogin.Secret);

    var request = new RestRequest(Method.POST);
    request.Resource = "{version}/files/dropbox{path}";
    request.AddParameter("version", _version, ParameterType.UrlSegment);
    request.AddParameter("path", path, ParameterType.UrlSegment);
    //Need to add the "file" parameter with the file name
    request.AddParameter("file", localFile.Name);

    request.AddFile(new FileParameter { Data = bytes, FileName = localFile.Name, ParameterName = "file" });

    var response = restClient.Execute(request);

    return response.StatusCode == System.Net.HttpStatusCode.OK;
}

Ok to start with the “path” variable/parameter is the folder path (not the file).

Starts off the same with the RestClient, JsonDeserializer and the OAuthAuthenticator. We also need to read the file as a byte array. Now this request is a POST so we set that in the RestRequest object then add the version and path Url parameters. We also need to add the Filename as a “file” parameter for this request as well as adding the actual file to the Request. Execute that and: {\"result\": \"winner!\"} we just uploaded a file to dropbox!

 

This code was taken from my Dropbox open source .NET project called DropNet.

Dropbox API and RestSharp for a C# developer

Filed Under (Code) by admin on 18-05-2010

Tagged Under : , , ,

The Dropbox API has foiled my development of “Droppedboxx” for some time now. Mainly because the on site documentation is average for anyone not planning on developing for the iphone (dropbox, you used to be cool). Being a C# developer this was bad news for me but I decided to give it a go anyway and after a few weeks of failed attempts and a few emails to support about my issues I realised the API documentation on the dropbox website is slightly wrong.

So now that I have it working I thought i’d share this with my fellow .NET developers (and anyone else who will care to listen).

What you will need (What i used):

  • RestSharp (What would i do without you…)
  • Oauth Library for C# (this one seems the easiest to use with RestSharp)
  • Access to the Dropbox API and an APIKey/Secret for your app

I guess I should start with the Setup of it, I started this as a Windows Mobile application but I switched to a .NET library so I could test it easier and also use RestSharp (might open source the library if I get around to it).

 

Login, this is possibly the easiest method if you have the right URL (the API documentation give you the wrong URL). We should be using “https://api.getdropbox.com/0/token” Code you say?

Update: Got some helpful advice about using the request.Resource property with parameters instead of a string.format.

public UserLogin Login(string email, string password)
{
    var restClient = new RestClient("https://api.getdropbox.com");
    var request = new RestRequest(Method.GET);
    request.Resource = "{version}/token";
    request.AddParameter("version", _version, ParameterType.UrlSegment);

    request.AddParameter("oauth_consumer_key", _apiKey);

    request.AddParameter("email", email);
    request.AddParameter("password", password);

    var response = restClient.Execute<UserLogin>(request);

    _userLogin = response.Data;

    return response.Data;
}

Seems pretty easy right? Most of thats RestSharp (with the JSONDeserializer), I then have the UserLogin class which is returned by this function.

public class UserLogin
{
    public string Token { get; set; }
    public string Secret { get; set; }
}

And now your user is logged in, you will then want to store the Users Token and Secret (storing UserLogin object would probably be better) as its used for the rest of the requests. I’ll just show you how to get the User Info as the other requests differ from the login (that is where we’ll need the Oauth stuff).

 

Account/Info, I’ll start with the Response classes this time…

public class AccountInfo
{
    public string Country { get; set; }
    public string Display_Name { get; set; }
    public QuotaInfo Quota_Info { get; set; }
    public string Uid { get; set; }
}

public class QuotaInfo
{
    public string Shared { get; set; }
    public string Quota { get; set; }
    public string Normal { get; set; }
}

These are the classes for RestSharp to Deserialize the JSON to. Pretty simple, this is straight off the API Documentation site. Now for the actual request…

public AccountInfo Account_Info()
{
    var restClient = new RestClient("http://api.dropbox.com");
    OAuthBase oAuth = new OAuthBase();
    string nonce = oAuth.GenerateNonce();
    string timeStamp = oAuth.GenerateTimeStamp();
    string normalizedUrl;
    string normalizedRequestParameters;
    string sig = oAuth.GenerateSignature(new Uri(string.Format("{0}/{1}/account/info", restClient.BaseUrl, _version)),
        _apiKey, _appsecret,
        _userLogin.Token, _userLogin.Secret,
        "GET", timeStamp, nonce, out normalizedUrl, out normalizedRequestParameters);
    sig = HttpUtility.UrlEncode(sig);

    var request = new RestRequest(Method.GET);
    request.Resource = string.Format("{0}/account/info", _version);
    request.AddParameter("oauth_consumer_key", _apiKey);
    request.AddParameter("oauth_token", _userLogin.Token);
    request.AddParameter("oauth_nonce", nonce);
    request.AddParameter("oauth_timestamp", timeStamp);
    request.AddParameter("oauth_signature_method", "HMAC-SHA1");
    request.AddParameter("oauth_version", "1.0");
    request.AddParameter("oauth_signature", sig);

    var response = restClient.Execute<AccountInfo>(request);

    return response.Data;
}

Now, this request has a different Base Url to the Login function and this uses OAuth. So firstly we create an instance of the RestSharp client and the OAutheBase classes. The OAuthBase class then handles all of the oauth parameters that we need to make the Request (nonce, timestamp, etc.). GenerateSignature is the main 1 that rolls up the request path and the tokens/secrets into a hash for extra security. As for the dropbox part of this, we dont need any extra parameters as we are just getting the logged in users Account Info. Then its just a matter of adding these parameters to the RestRequest object, notice the oauth_token is actually the UserLogin.Token that we got from our Login method?

 

Stay tuned for more, Tales of interest!

 

Update: I have added a Part 2 to this post.

MVC2 Cascading Dropdown Lists with JSON

Filed Under (Code) by admin on 04-05-2010

Tagged Under : , ,

Today I’m going to show you how to go about creating cascading dropdown lists using JSON in MVC2. Hold onto your hats, its time to begin!

Learning ASP.NET MVC2 I thought I’d start with a relatively simple web application, this application is for keeping track of service usage across the company’s physical sites (ie. Electricity, Gas, Waste, etc.).

Now first things first, I setup the Database and LinqToSql classes for my app. The table structure is MeterTypes > MeterCollections > MeterUsages. Where a MeterType is the top level (ie. Electricity, Gas, Waste, etc.) the MeterCollections are the next level down (a MeterType may contain many of these, for Electricity I have Peak and Off-Peak) and MeterUsage is the actual usage on a meter for that MeterCollection.

 

OK, lets get coding… We will be looking at the Create Page for the MeterUsage object, I started with the create template MVC2 gave me for this object (half of the fields are just textboxes anyway)

public ActionResult Create()
{
    var meterTypesRepo = new Models.Repo<Models.MeterType>();
    var meterTypes = from mt in meterTypesRepo.Many()
                     select new SelectListItem
                     {
                         Value = mt.MeterTypeID.ToString(),
                         Text = mt.Name
                     };
    ViewData["meterTypes"] = meterTypes;

    return View("Create");
} 

Inside the Controller is where the request is handled, Now we need the data for the first list so we may as well get this here. This simply gets all the MeterTypes in the Database and converts them to SelectListItems (this is to make it easier on the page)

<div class="editor-label">
    <label for="meterTypes">Meter Type</label>
</div>
<div class="editor-field">
    <%= Html.DropDownList("meterTypes", "-- Select --")%>
</div>
<div class="editor-label">
    <label for="MeterCollectionID">Meter Collection</label>
</div>
<div class="editor-field">
    <%= Html.DropDownListFor(model => model.MeterCollectionID, new SelectList(new List<UsageInputs.Models.MeterCollection>()))%>
    <%= Html.ValidationMessageFor(model => model.MeterCollectionID) %>
</div>

Markup, Basic use of the Html.DropDownList() function for MeterTypes (this is where using SelectListItems comes in handy. Also added a default option “—Select –”. Then the MeterCollection Dropdown is a little different as this one actually maps to a property on my MeterUsage object so I used the Html.DropDownListFor() function and gave it an empty list so it would create the dropdown list but not have any items (they will be populated with Ajax.

Next is the Javascript, this simply calls my MeterCollections/GetList function with the ID of the MeterType from the selected item in the DropDown list.

$("#meterTypes").change(function () {
    $.ajaxSetup({ cache: false });
    var selectedItem = $(this).val();
    if (selectedItem == "" || selectedItem == 0) {
        //Do nothing or hide...?
    } else {
        $.getJSON('<%= ResolveUrl("~/MeterCollections/GetList/")%>' + $("#meterTypes > option:selected").attr("value"), function (data) {
            meterCollections = data;
            var items = "";             $.each(data, function (i, meterCollection) {
                items += "<option value='" + meterCollection.Value + "'>" + meterCollection.Text + "</option>";
            });
            $("#MeterCollectionID").html(items);
        });
    }
});

It also builds up the html for inside the dropdown list using a JQuery for each loop.

Now the last part is our GetList function to return JSON, so back to the controllers.

[HttpGet]
public ActionResult GetList(int id)
{
    var meterCollsRepo = new Models.Repo<Models.MeterCollection>();
    var meterCollections = from mc in meterCollsRepo.Many()
                           where mc.MeterTypeID == id
                           select new SelectListItem
                           {
                               Text = string.Format("{0} ({1})", mc.Name, mc.Mesurement),
                               Value = mc.MeterCollectionID.ToString()
                           };

    return Json(meterCollections, JsonRequestBehavior.AllowGet);
}

This function then gets all the MeterCollections that have that MeterTypeID. Here I also use the SelectListItem object as its much easier to work with in the Javascript and less work for the Serializer.

 

And just like that you have a Cascading DropDown List in MVC2 using Ajax.

Smack my BitSharp!

Filed Under (Code) by admin on 29-04-2010

Tagged Under : , , ,

Its an open source .NET client for the BandsInTown API.

TBODA currently have a number of web projects that focus on Live music, such as Promote.fm, and through these projects I have worked very closely with a lot of gig guide APIs. So i thought I’d make some of my code reusable but not just by me, thus BitSharp was born.

Now I’m a big fan of RestSharp (The .NET Rest Client) so BitSharp uses it for all the API requests and Responses. BitSharp is still in early development but most of the event and artist functions are working.

 

Now for the code to us it:

var client = new BitClient("API_KEY_HERE");

Artist artist = null;
try
{
    artist = client.Artists_Get("de11b037-d880-40e0-8901-0397c768c457");
}
catch (BitException ex)
{
    Console.WriteLine("BandsInTown Error:" + ex.Message);
    return;
}

Console.WriteLine(artist.Name);
Console.WriteLine(artist.MusicBrainzID);
Console.WriteLine("Bytes received: " + client.DataCount);

 

Starting by creating an instance of the BitClient with the APIKey this object is then what we use to make all the requests to the API so its a good idea to keep this at the global level that way you only need 1 instance.

Then inside the Try/Catch is where we call the Artists_Get function (this function simply gets artist info given the MusicBrainz ID). All the API Functions throw a BitException if an error is returned from the API so this exception is then caught.

Now that we have called the Artists_Get function we get an Artist object returned and its as easy as that.

 

The other BitSharp functions currently implemented include: (Updated)

  • Events_Search (Search for events either by artist(s), location or date)
  • Events_Daily (Returns a list of events that have been created updated or deleted in the last day)
  • Events_Recommended (Gets recommended events either by artist(s), location or date)
  • Artists_Events (Returns an artists upcoming events)
  • Artists_Get (Gets information on a single Artist)
  • Venues_Search (Search for venues by name and/or location)
  • Venues_Events (Returns a venues upcoming events)

 

You can find the source for BitSharp @ Github.

Parallel vs. Async Email performance

Filed Under (Code) by admin on 23-04-2010

Tagged Under : , , ,

Lately i have been doing some work with sending emails and I have chosen to use some of .NET4.0’s Parallel processing and the FluentEmail library.

I then got thinking about the Performance differences between using Parallel against Asynchronous so I decided to run some tests. Based of the C# Micro Performance Testing Class blog post I have written a simple app for testing this.

 

Firstly I created my base class for the performance tests, this will later be inherited by by different testers.

Pretty basic, methods to start and finish that set the stopwatch and the finished bool…

public abstract class PerformanceTester
{
    public TimeSpan TotalTime { get; private set; }
    public TimeSpan AverageTime { get; private set; }
    private Stopwatch _stopwatch;
    public int Iterations { get; private set; }
    public bool Finished { get; private set; }

    public PerformanceTester()
    {
        Finished = false;
    }
    public virtual void Run(int iterations)
    {
        Iterations = iterations;
        _stopwatch = Stopwatch.StartNew();
    }
    public void Finish()
    {
        _stopwatch.Stop();
        AverageTime = new TimeSpan(_stopwatch.Elapsed.Ticks / Iterations);
        TotalTime = _stopwatch.Elapsed;
        Finished = true;
    }
}

Now that we have the stone to build off we can create the classes for the tests we went to perform, in this case 1 for Async and 1 for Parallel (below) these 2 classes then just override the Run method and call Finish when its done. However the async class differs slightly as it has to wait for the async callback.

 

public class ParallelEmails : PerformanceTester
{
    public override void Run(int iterations)
    {
        base.Run(iterations);
        //do stuff here
        Parallel.For(0, iterations, i =>
            {
                //send emails
                Email.From(Settings.FromAddress)
                    .To(Settings.ToAddress)
                    .Subject(Settings.Subject + "P" + i)
                    .Body(Settings.Body)
                    .UsingClient(new SmtpClient(Settings.HostAddress))
                    .Send();
            });
        //all done
        base.Finish();
    }
}
public class AsyncEmails : PerformanceTester
{
    private int _currentIteration;

    public override void Run(int iterations)
    {
        base.Run(iterations);
        //do stuff here
        for (int i = 0; i < iterations; i++)
        {
            Email.From(Settings.FromAddress)
                        .To(Settings.ToAddress)
                        .Subject(Settings.Subject + "A" + i)
                        .Body(Settings.Body)
                        .UsingClient(new SmtpClient(Settings.HostAddress))
                        .SendAsync(emailCallback);
        }
    }
    private void emailCallback(object sender, EventArgs e)
    {
        _currentIteration = _currentIteration + 1;
        if (_currentIteration == Iterations) Finish();
    }
}

Now for some results, now I know the performance will differ depending on PC hardware so I’m testing this on 2 different PCs the first has a Core 2 Duo E6400 @ 2.13GHz and the 2nd has a Core 2 Quad Q6600 @ 2.4GHz.

Table represents my results of the tests (in milliseconds)

Emails Sent Parallel (Dual Core) Parallel (Quad Core) Async

(Dual Core)
Async

(Quad Core)
1 6019 5716 6107 7039
8 26642 39571 34291 25638
15 59282 46897 58849 47730
20 70977 67488 62120 79164

Just a note, these tests were run from the 2 PCs on the same network with the same internet connection connecting to gmails smtp server. Of course there are other factors that would affect performance of these 2 methods but this is just to get an idea of the differences.

Read into that as much as you want but the main thing i got from it is parallel processing is better when you have more cores (which isn’t really anything new at all). Good to see the difference in results though.

 

DK out…

Fluid.NET controls for Windows Mobile 6

Filed Under (Code, Mobile) by admin on 20-04-2010

Lately I have been making an application for Windows mobile but I am pretty bad with design so I was looking for a control toolkit and came across the Fluid.NET controls, which is an open source control toolkit for Windows Mobile. Now there wasn’t too much documentation on the site and it hadn’t been updated for a while but they had a pretty decent looking example application which they offered the source for.

 

Screenshot1I based my project off their example, took me a while to figure out how to use some of their controls but now i have a bit more of an idea and i thought I’d share it.

Basically I’m trying to use the Fluid.NET listbox control to display the file system (so i can select a folder).

I started by using the ListBoxBase class from PasswordSafe, this class handles the general list type stuff, like changing the colour of selected list items etc.

Then I created a new Fluid Template this is the class used by the ListBox to populate the items in the list. Item layout goes in the InitControl() method then the actual content of the Item (In my case its based off a DirectoryInfo object) goes in the OnBindValue() method.

public class AddFolderTemplate : FluidTemplate
{
    private FluidLabel nameLabel;
    private FluidLabel secondaryLabel;

    protected override void InitControl()
    {
        base.InitControl();
        this.Bounds = new Rectangle(0, 0, 240, 64);
        nameLabel = new FluidLabel("", 3, 0, 228, 64 - 3);
        Controls.Add(l);
        secondaryLabel = new FluidLabel("", 8, 62 - 12, 224, 12);
        Controls.Add(l);
    }
    protected override void OnBindValue(object value)
    {
        var folder = value as DirectoryInfo;
        if (folder != null)
        {
            nameLabel.Text = folder.Name;
            secondaryLabel.Text = folder.FullName;
        }
    }
}

After I had the Template done I then created my listbox class (inheriting from the ListBoxBase) This class didnt need to do too much as most of the work is done in its base and the panel it goes in.

public class AddFolderListBox : ListBoxBase
{
    private NotifyList folders;
    public event EventHandler FolderSelected;

    protected override void InitControl()
    {
        base.InitControl();
        ItemHeight = 32;

        ItemTemplate = new AddFolderTemplate();
    }
    public NotifyList Folders
    {
        get { return folders; }
        set
        {
            if (folders != value)
            {
                folders = value;
                DataSource = value;
            }
        }
    }
    ...
}

Now that we’ve got the classes done, time to put them to use. I have created a panel for browsing through the file system. All we need to do here is create an instance of our Listbox control and add a list of folders to the Folders Property.

Controls.Add(lsbFolders);
CurrentDir = new DirectoryInfo("/");
lsbFolders.Folders = MakeDirList(CurrentDir.GetDirectories());

This then loads all the folders in the devices root into the listbox. I have also added to the OnItemClick event to go deeper into the file system and a back button to go back to the parent directory.