Amadiere.com

Fourteen and a half crazy frog burpers

10th September 2010

Isolated Storage on Windows Phone 7

Filed under: C#,Databases,Windows Phone 7 — Tags: , , , — Alex Holt @ 9:30 pm

One of the most amazing omissions from the Windows Phone 7 OS is an SQL Server of some description that applications can use (I think there is a SQL Server Compact edition baked into the build, but it’s only exposed to the native apps). This leaves anyone familiar with doing all their storage via relational databases in a bit of a lurch.

Having a look around, there were a few work-arounds, namely third party libraries such as Perst & Sterling. These act as a layer of abstraction that allow you to use LINQ to access your objects and could be of benefit for some of the more complex applications. I found both of them to have their drawbacks.

Perst: From McObject is one alternative, but if you plan on doing a commercial application, you should bare in mind their licensing, of which, their FAQ says:

No, Perst is not free. McObject Perst is available under a dual license. Under the GPL, you may evaluate the source code free of charge and you may use Perst free of charge in an application for which the source code is also freely available. If you wish to use a Perst in an application but do not or cannot redistribute your application source code, you can use Perst under a commercial license.

Sterling: This seemed promising, but I had a number of issues getting the code to work (it was late, in fairness) I decided to give up.

In reality though, most applications that are going to be made don’t need any complicated database structure behind them. Database implementations are most likely going to be overkill. This is where I decided to do what probably the majority of WP7 developers have decided to do, and “Roll-Their-Own” database solution. Mine is based on a general accepted practice, using XML Serialisation to store my POCOs. While it might have limitations and performance issues later down the line, for now – it’s performing very admirably and there seemed no point in premature optimisation just yet.

My Solution

The main class I created (MyDataContext.cs) contains the functions for both saving and loading the data, as well as the ‘schema’ for the entire database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;
using System.Collections.Generic;
using IsolatedExampleApp.Data.Models;
using System.IO.IsolatedStorage;
using System.IO;
using System.Xml.Serialization;
 
namespace IsolatedExampleApp.Data
{
  public class IsolatedDatabase
  {
    public IsolatedDatabase()
    {
      // For each model that is a list item, you need to add a initialising statement to the Constructor
      Albums = new List();
      Artists = new List();
    }
 
    // These properties effectively form the publicly viewable schema of the database.
    public List Albums { get; set; }
    public List Artists { get; set; }
    public Options Options { get; set; }
 
    public void Load()
    {
      using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
      using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("IsolatedExampleApp.txt", FileMode.OpenOrCreate, FileAccess.Read, store))
      using (StreamReader reader = new StreamReader(stream))
      {
        XmlSerializer serializer = new XmlSerializer(typeof(IsolatedDatabase));
        var unserialized = reader.EndOfStream ? new IsolatedDatabase() : (IsolatedDatabase)serializer.Deserialize(reader);
 
        // Each schema is repopulated with information when the app is loaded.
        Albums = unserialized.Albums;
        Artists = unserialized.Artists;
        Options = unserialized.Options;
      }
    }
 
    public bool Save()
    {
      try
      {
        using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
        using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("IsolatedExampleApp.txt", FileMode.Create, FileAccess.Write, store))
        {
          XmlSerializer serializer = new XmlSerializer(typeof(IsolatedDatabase));
          serializer.Serialize(stream, this);
        }
        return true;
      }
      catch (Exception ex)
      {
        return false;
      }
    }
  }
}

As you can see from the code above, as you develop more data stores, the code needs updating in multiple locations.

  • Properties need setting for each one (they are the publicly available access points for the data).
  • Any LISTS<> require their lists initialised by the Constructor method.
  • When the data is ‘Load()’ed, each property must have it’s values manually set.
  • All the Models still need defining elsewhere in your application (in my example above, they are in the IsolatedExampleApp.Data.Models namespace.

If you can overlook this repeated typing, then this seems to be a good starting point for persisting data in your Windows Phone 7 Application. To use it should then be fairly straight forward.

_db = new IsolatedDatabase();
_db.Load();
 
// Adding an album...
_db.Albums.Add(newAlbum);
_db.Save();
 
// Deleting an album...
_db.Albums.Remove(deleteAlbum);
_db.Save();
 
// Add or Update an album...
Album existingAlbum = _db.Albums.Where(x => x.ID == album.ID).FirstOrDefault();
if (existingAlbum != null)
{
  Delete(existingAlbum);
}
Add(album);
_db.Save();
 
// Or just getting a specific album...
IEnumerable albums = _db.Albums as IEnumerable;
return albums.Where(x => x.ID == id).FirstOrDefault();

Any feedback, thoughts, options and optimisations for the above code will be well received. Happy isolating!

6th April 2010

Development SMTP Servers for IIS7.5 on Windows 7

Filed under: ASP.NET,C# — Tags: , , , , , — Alex Holt @ 3:43 pm

I’ve had one of them days. You know? That “simple task” that spiralled out of control and resulted in me losing half a day to it’s tricks! That task? It was sending an email from an ASP.NET (MVC2) application. Previously, I’ve always done this via setting up IIS and the SMTP server in there, but for some reason, Microsoft decided they didn’t want to include the SMTP Server in Windows 7 anymore (even ‘Ultimate’ – it might also be the case for Windows Vista). So, I had to find an alternative.

There were a few options available to me:

  • SMTP Server on Localhost: This was the obvious choice, but after trying Mercury Mail and it’s quarter of a million settings as it installed (I’m no Email Admin, so didn’t know the answer to all of them). It didn’t work and I’m not sure why. To rub salt into the would, there was no uninstall either – it proper irritated me and I gave up using it out of principal.
  • SMTP Server on Localhost that is really just a Relay. Well, sounded good – but again, it was designed by people with bigger brains than me and it failed to send to what I thought was a correctly configured IIS7.5 config pointing to my GMail account.
  • Fake Server: Something that doesn’t actually send emails, but pretends to.

The last one is the one I eventually choose and boy am I glad I did! I downloaded the excellent SMTP 4 DEV from Codeplex

  1. I don’t have 100′s of emails cluttering up my email box for starters. Win!
  2. It was so easy to set-up and it worked perfectly without a change to my code. Win!
  3. It’s free. Win!

Here is some fake code that should send an email to the localhost.

MailMessage emailMessage = new MailMessage();
string messageBody = "This is the content of the email will be awesome!";
 
emailMessage.Body = messageBody;
emailMessage.Priority = MailPriority.Normal;
emailMessage.From = new MailAddress("no-reply@amadiere.com"); // obviously, this email address doesn't exist :)
emailMessage.Subject = "The answer is 42";
emailMessage.IsBodyHtml = false;
 
SmtpClient mSmtpClient = new SmtpClient();
mSmtpClient.Host = "127.0.0.1";  // localhost
mSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
 
mSmtpClient.Send(emailMessage);

15th March 2010

Good Quality Image Resizing in C#

Filed under: C# — Tags: , , , — Alex Holt @ 8:40 pm

I encountered a little bit of a problem the other day with some image resizing code from within an ASP.NET MVC application that was misbehaving. The issue was just a general C# and ASP.NET one, not related to MVC or Webforms, but it was that for some reason the images were losing a significant amount of quality when resizing. I’m talking a pixel sharp 2000 x 2000 picture that when resized to 300 x 300, was woefully blurry. Initially, the code was simply using the GetThumbnailImage() method to produce it’s resizes, this turned out to be the mistake!

While GetThumbnailImage() is fine for small thumbnail images (the clue I guess, was in the name), it somewhat struggled on the larger versions. To fix the issue, I had to convert the image to a bitmap, faff about with it like that, then export it back to a Jpeg once I was done.

For future me (and anyone else this might help), here is the code I eventually settled on:

EncoderParameters encodingParameters = new EncoderParameters(1);
encodingParameters.Param[0] = new EncoderParameter(Encoder.Quality, 90L); // Set the JPG Quality percentage to 90%.
 
ImageCodecInfo jpgEncoder = GetEncoderInfo("image/jpeg");
 
// Incoming! This is the original image. This line can effectively be anything, but in this example it's coming from a stream.
var image = Image.FromStream(new System.IO.MemoryStream(Picture));
 
// Creating two blank canvas. One that the original image is placed into, the other for the resized version.
Bitmap originalImage = new Bitmap(image);
Bitmap newImage = new Bitmap(originalImage, 300, (image.Height * 300 / image.Width));  // Width of 300 & maintain aspect ratio (let it be as high as it needs to be).
 
// We then do some funky voodoo with the newImage. Changing it to a graphic to allow us to set the HighQualityBilinear property and resize nicely.
Graphics g = Graphics.FromImage(newImage);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
g.DrawImage(originalImage, 0, 0, newImage.Width, newImage.Height);
 
var streamLarge = new System.IO.MemoryStream();
newImage.Save(streamLarge, jpgEncoder, encodingParameters);
 
// This is the line that returns the picture to the relevant part of the model.
_event.Picture = streamLarge.ToArray();
 
// No need for all that drama for the thumbnail, the loss of quality isn't noticable.
var thumbnail = image.GetThumbnailImage(80, (image.Height*80/image.Width), null, new IntPtr(0));
var streamThumbnail = new System.IO.MemoryStream();
 
thumbnail.Save(streamThumbnail, jpgEncoder, encodingParameters);
 _event.ThumbnailPicture = streamThumbnail.ToArray();
 
// Good boy's tidy-up after themselves! :O
originalImage.Dispose();
newImage.Dispose();
thumbnail.Dispose();
streamLarge.Dispose();
streamThumbnail.Dispose();
« Newer PostsOlder Posts »

Theme designed & built for Amadiere.com by Alex Holt. Powered by WordPress