A while ago I had the idea to generate Badges automatically on Windows Azure.
Using the standard imaging functions of .NET to generate layered graphics seemed a bit of an overhead, because of the wide varieties of badges that will be used in a certain solution .
Therefore I was looking for something more compact, structured and something that could easily generate the desired templates in a good/excellent quality – SVG!
What is SVG?
SVG is a language for describing two-dimensional graphics in XML [XML10]. SVG allows for three types of graphic objects: vector graphic shapes (e.g., paths consisting of straight lines and curves), images and text. Graphical objects can be grouped, styled, transformed and composited into previously rendered objects. The feature set includes nested transformations, clipping paths, alpha masks, filter effects and template objects.
You can read more about the SVG standard on the W3C site: Scalable Vector Graphics (SVG) 1.1 (Second Edition)
Great, but how can I modify existing SVG files using C# ?
Usually Linux is the number one address to modify, transform and convert XML files of all kinds and thousands of standards. The first thing that came to my mind thinking about SVG and how to use it in .NET was Incscape.
Incscape – an Open Source vector graphics editor, with capabilities similar to Illustrator, CorelDraw, or Xara X, using the W3C standard Scalable Vector Graphics (SVG) file format.
The plan was to use the Incscape libraries and use them via P/Invoke or other mysterious ways. But since all the stuff is GTK or Python based, I preferred to look for a simpler (and faster) solution to implement a basic version of the service.
Browsing the internet for a while, I stumbled over SVG .NET. After some tests with the source and presenting the results on Twitter, I was pretty sure to use this library. Two buddies of mine, Marco Siccardi and Alex Bouma where infected by the idea and pushed me on Twitter to do the implementation.
<script async src="http://www.codeproject.com/platform.twitter.com/widgets.js" charset="utf-8"></script>
<script async src="http://www.codeproject.com/platform.twitter.com/widgets.js" charset="utf-8"></script>
The basic idea – simplified
Create a web service that enables users to upload SVG templates and turn them into badge images. That should be possible for Windows Phone, WinRT and .NET in general. Backend runs on Windows Azure.
Basic solution structure
To give you a quick overview of the solution structure I generated this code-map:
- BadgeService.dll – The Azure Worker Role, hosting OWIN hosting the Web API
- Services.dll – Interface definitions for storage implementations and badge generation
- BadgeServicePCLClient – The PCL client to access the Web API hosted in the Azure Worker Role
- BadgeAdmin.dll – Core of the MVC5 project, used to manage SVG data
- ConsoleTestClient.exe – Implementation to demonstrate how to use the service from within a console application
- TestBadgeGenerator – A simple Windows Phone 8 project to demonstrate how to use the service on Windows Phone (project name misleading, sorry for that, will be changed)
- Model.dll – The model classes to be used on the client and server side to exchange information
Technology Stack
For this project the following SDKs, tools and components have been used:
- Windows Azure SDK 2.2Visual Studio 2013 RTM
- Windows Phone 8 SDK
- PCL 4.6
- Azure Worker Role
- Unity for dependency injection
- OWIN hosted Web Api
- TAP – Async/Await
- ASP .NET MVC 5 using asynchronous controllers
- SVG.NET implementation to replace SVG content: Download it here => SVG.NET
Download the source code
The source-code is hosted on GitHub => AzureBadgeGenerator
Setup
Basically you download the entire source and compile it in Visual Studio 2013 RTM. To be able to compile the source, you need the latest Windows Azure SDK. You can download the latest Windows Azure SDK here: Windows Azure SDK for .NET Download Page
Before you compile the solution, you have to set some important configuration values to make the solution work. Mainly those settings are SQL Server connections.
- The SQL Server connection string for the SVG-Admin interface
- The SQL Server Settings for the Worker Role
Change the SQL Server connection settings for the SVG-Admin Interface
The changes need to be done in Web.config. Please search for “BadgesEntities” and replace the following parts:
<add name="BadgesEntities"
connectionString="metadata=res://*/Models.Badges.csdl|res://*/Models.Badges.ssdl|
res://*/Models.Badges.msl;provider=System.Data.SqlClient;provider
connection string="data source=[DATABASESERVER];user id=[USERNAME];
password=[PASSWORD];MultipleActiveResultSets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
- Replace [SERVERNAME] with your SQL Server instance (without the square brackets)
- Replace [USERNAME] with your SQL Server user (again without the square brackets)
- Replace [PASSWORD] with your SQL Server user, password (again without the square brackets)
Change the SQL Server connection settings for the Azure Worker Role
Expand the Worker Role project (That one with the cloud symbol) and look for the “BadgeService” entry. Right click on “BadgeService” and select “Properties”. Select the “Settings” tab and change the value “SqlConnection” according to your SQL Server/Azure SQL settings.
Create the SQL Server/Azure SQL database and the Badges table
First of all, you need to create a local SQL Server database or an Azure SQL database. If you want to test locally, you can install the latest version of SQL Server Express. You can download SQL Server 2012 Express here: SQL Server Express 2012 Download
There is a folder called “SQL” located inside the “BadgeService” project. You can find 2 files there:
- SQLAzure.sql (Use that to execute it against an Azure SQL database)
- SQLServerLocal.sql (Use that to execute it against a local SQL Server installation)
The nice thing is, that you can execute the scripts from within Visual Studio. You can also fire-up SSMS (SQL Sever Management Studio) and connect to your Azure SQL database or to your local database. In both cases execute the appropriate script against your database.
Access the service locally from within Windows Phone 8 Emulator
Developing Azure services and testing API’s locally is a PITA. To be able to access the badge service from within Windows Phone emulator you need to open a command session as administrator and execute the following command:
C:\Windows\system32>netsh interface portproxy add v4tov4 listenport=800 connecta
ddress=127.255.0.0 connectport=81 protocol=tcp
This will allow you to access the Badges service like this: http://[YOURPCNAME]:800/badgeservice/[CONTROLLERACTION] . It will work also in your local network. All credits for this tip go to Sandro Di Mattia: Remotely accessing the Windows Azure Compute Emulator
How to use it
Create a SVG template using Inkscape
Here is a short video on how to quickly create a badge template that can be used with the badge generator:
Server Side – Upload SVG data
<iframe width="560" height="315"
src="http://www.codeproject.com/www.youtube-nocookie.com/embed/jqsxudLu8Bk"
frameborder="0" allowfullscreen=""></iframe>
Client Side – Define template values and request a PNG file
Using the Badge service to generate badges on the fly is pretty easy. Just add a reference to this two projects to your .NET, Windows Phone 8 or WindowsRT app:
- Model (Contains all the base classes to handle the badge data)
- BadgeServicePCLClient (send requests against the badge service)
Here is a short sample (taken from the Windows Phone sample):
BadgeServiceClient cl = new BadgeServiceClient("http://[YOURSERVICEHOST]:800/badges");
BadgeGenData data = new BadgeGenData();
data.BadgeName = "test";
data.BadgeData.Add(new BadgeTextContent(){ElementName =
"text3003", Value=this.txtBadgeparam.Text});
var imageData = await cl.CreateBadgeImage(data);
if(imageData != null)
{
if(imageData.Length > 0)
{
BitmapImage bitmapImage = new BitmapImage();
try
{
using (MemoryStream ms = new MemoryStream(imageData))
{
bitmapImage.SetSource(ms);
this.imgBadge.Source = bitmapImage;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
First you create the BadgeServiceClient
and add a valid url. In this case you can see the local service URL, when testing the service locally, after applying the netsh settings.
Next thing that needs to be done is to create a new instance of the BadgeGenData
class. This class is responsible to replace text in a specific SVG saved in the badges table.
You set the BadgeName
and create a bunch of properties key/value pairs to replace SVG text-properties with your custom text. Then you call the CreateBadgeImage
method, that will return the bytes of the generated PNG file. You can convert these bytes to an imageSource
and assign it to an image control or save it for later use.