Monday, 9 November 2009
Passing a User Generated Image From Adobe Flash to ASP.NET
I have four years experience with ASP.NET from my day job at a Leading UK Marketing Agency and about a million years experience with Flash from being a student at the Hull School of art and Design, teaching Interactive Multimedia at the University of Lincoln and using it in personal and professional projects.
I'm a massive fan of StackOverflow and find it an invaluable resource, so in the interest of giving a little bit back to the community, I placed a bookmark on my desktop with the intention of writing a solid answer to the question.
Four months go by and finally, I get round to doing it. And so, you can now read about how to send a generated image from Adobe Flash (using ActionScript 3) to an ASP.NET backend and hopefully my karmic daemons will leave me alone for another week.
Sunday, 14 June 2009
Outputting the Subversion revision into your web page
A few months ago when I stared using stackoverflow I noticed that they output the current Subversion revision number into their html source.
This is both cool and useful and as I’m about to become a SVN Nazi and make sure that all new projects at work are placed under source control (only a few are at present) I wanted to know how to do it.
Getting the tools
Most of our projects are built using ASP.NET so I wanted to know how to get this working from within Visual Studio. Thankfully this didn’t take long, a few Google’s turned up MSBuild Community Tasks Project hosted over at Tigris.org who are the good folks behind Subversion and many many Subversion tools. I had a quick look over the list of tasks and spotted the “SvnVersion” task and thought that sounds about right. I downloaded and installed the Community Tasks.
I also downloaded the Visual Studio Web Deployment projects after having read ScottGu’s blog post regarding them. You can get the VS2008 version here or the VS2005 version here if you need it.
Getting the revision into your HTML
To get the revision number into my HTML I chose to add a Web Deployment project (right click on your website/web app in the solution explorer and “Add web deployment project” then right click on this new project and “Open project file”. What you’ll see now is the XML of the MSBuild file and towards the bottom of this file should be a comment with four target tags in it like this.
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.WebDeployment.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="BeforeMerge">
</Target>
<Target Name="AfterMerge">
</Target>
<Target Name="AfterBuild">
</Target>
-->
We’re going to use the AfterBuild target so to place the revision number in a little bit of HTML that’s going to live in a master page, so let’s set up the master page first.
My site is a .NET MVC application and I’m going to add the revision number to the Site.Master. To do this I added the following HTML to the footer of the master page.
<span id=”rev”>revision REVISION</span>
The SvnRevision task will get the revision number from our working copy and store it in a property name that we define.
We can then use another Community Task, FileUpdate, to update the master page after the build.
Here is the XML of the AfterBuild target looks, note also that before the target I have imported the Community Tasks that we downloaded and installed earlier.
<!-- Import the community build tasks-->
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
<target name="AfterBuild">
<! -- Add the SvnVersion build task -->
<svnversion toolpath="$(ProgramFiles)\VisualSVN\bin" localpath="$(MSBuildProjectDirectory)">
<output propertyname="Revision" taskparameter="Revision" />
</svnversion>
<fileupdate replacementtext="revision $(Revision)" regex="revision REVISION" files="$(Configuration)\Views\Shared\Site.Master" />
</target>
The FileUpdate finds the string defined in the regex attribute and replaces it with the string in the replacementText attribute. $(Revision) is MSBuild syntax for a property (like a variable in other languages) where “Revision” is the property name. The files attribute tells the fileUpdate action which file to work with when doing this replacemnet. In this example $(Configuration) is a property that the build engine creates which contains the name of the current build configuration (Debug or Release are the defaults).
So to see this in action, right click on the Web Deployment Project and click Build. Then navigate to the solution folder. Inside that folder should be another folder named the same as your Web Deployment Project and in there, a folder for what ever configuration you had selected in Visual Studio (Debug is the default). Open this folder then browse to the folder containing the master page and open the master page in your favourite text editor. Find the span from the earlier step and you should see that the uppercase “REVISION” has been replaced with the current revision of your working copy.
Thursday, 4 June 2009
More CMS's, this time for PHP
I was after a small, easy to set up, flexible solution which wasn't going to take ages to install and configure and that also didn't require me to use a massive framework.
I friend recomended Pixie which is a free, open source offering from toggle and I've got to say that I was pleasantly supprised. Admittedly it's a million miles away from the object oriented nature of .NET that I'm so used to but it does have a plugin architecture and is easily skinnable.
I recomend giving it a try!
Wednesday, 27 August 2008
How to de-dupe a record set using a temporary table (MSSQL)
Following on from the SQL Fire we witnessed a while ago I've just wrote this rather snazzy little query that does something similar.
The Problem:
The original problem is we have a little game with a scoreboard and one very dedicated player. Well, not only one player, many players but one is more determined to win than the rest. So to keep the small scoreboard looking inviting we decided to only show each player once, and to only show that players highest score.
I really wanted to do this in SQL as I figured it’s sorting and ordering abilities would be far easier than writing something in C#.
The Solutions:
Select the data into a temporary table which has a unique index on the user ID. The order of the select will ensure that only the highest score for each user will make it into the temporary table. Then select everything out of said temptable.
The Practical:
-- CREATE THE TEMPORARY TABLE
CREATE TABLE #tmpTable (
strFirstName NVARCHAR(255),
strLastName NVARCHAR(255),
intScore INT,
intUserID_PK INT
)
-- ADD THE UNIQUE INDEX
CREATE UNIQUE INDEX ix0 ON #tmpTable (intUserID_PK) WITH (ignore_dup_key = ON)
-- INSERT THE DATA
INSERT INTO #tmpTable SELECT strFirstName,strLastName,strValue, intUserID_FK
FROM tblScores
-- THE ORDER IS THE WRONG WAY TO WHAT YOU THINK
-- IT SHOULD BE, ASC NOT DESC...
-- TRY IT THE OTHER WAY AND YOU SHOULD GET THE LOWEST SCORES
ORDER BY intScore ASC
-- SELECT THE DATA
SELECT * FROM #tmpTable
-- WITH THE CORRECT ORDER BY
ORDER BY intScore DESC
GO -- CALL GO SO THIS BATCH GETS EXECUTED AND THE TABLE IS NOLONGER USED
DROP TABLE #tmpTable
GO -- DROP THE TABLE SO IT IS NOLONGER IN MEMORY
Update: If you use this within a stored procedure you will need to remove the GO statements or the SP won't compile
Thursday, 26 June 2008
How to move the viewstate to the bottom of your page source (C# ASP.NET 2.0, 3.0, 2.5, Visual Studio 2005, Visual Studio 2008)
Andy did a couple of Google's and found some code which did the trick perfectly.
protected override void Render(System.Web.UI.HtmlTextWriter writer) {
System.IO.StringWriter stringWriter = new System.IO.StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
base.Render(htmlWriter);
string html = stringWriter.ToString();
int StartPoint = html.IndexOf("<input type="hidden" name="__VIEWSTATE");
if (StartPoint >= 0) {
int EndPoint = html.IndexOf("/>", StartPoint) + 2;
string viewstateInput = html.Substring(StartPoint, EndPoint - StartPoint);
html = html.Remove(StartPoint, EndPoint - StartPoint);
int FormEndStart = html.IndexOf("</form>") - 1;
if (FormEndStart >= 0) {
html = html.Insert(FormEndStart, viewstateInput);
}
}
writer.Write(html);
}
This was ace and so today when I was asked to upload some ammends to a couple more of our clients sites I thought I would implement this for the same reasons as it only takes two seconds.
While it worked a treat on one of the sites, the other was not so good. Here's what the page should look like:


What has happened is this. The un-styled UL that you can see at the top of the page is the top half of the left hand navigation you can see in the 1st picture. This menu was implemented as a .NET user control and as such is treated like a page all of its own. The reason this happened is because the page was rendering out via our overridden method, but the control was not. So the HTML that the control generated was getting written to the output stream before the HTML of the Page ("Page" in the .NET Class sense, not the "web page" sense).
So this got me thinking, wouldn't it be nice to be able to have a single piece of code that could be applied to a site once, regardless of UserControls, MasterPages or any other intricacy, that would take care of moving the ViewState on every page of the site!?!
The answer: Yes!
The solution: an HttpModule...
An HttpModule is a piece of code that sits between your web application and IIS on the web server. What this module is going to do is intercept every response our application makes to a client and then, if the response is a HTML (read ASPX) page, look for and move the ViewState.
To do this we will filter the response stream using the Response.Filter property. I'll leave the full code until the end of the post but here are the main bits.
1) Create a new class that implements IHttpModule.
public sealed class IHttpViewstateMover : IHttpModule {
2) Add an event handler to the current request. This even then decides weather to add our filter to the response stream based on if it is outputting HTML.
public void Init (HttpApplication context) {
context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);
}
void context_ReleaseRequestState (object sender, EventArgs e) {
HttpResponse response = HttpContext.Current.Response;
if ( response.ContentType == "text/html" ) {
response.Filter = new ViewstateMover(response.Filter);
}
}
3) If the entire HTML file has been output ...
Regex eof = new Regex("</html>", RegexOptions.IgnoreCase);
if ( !eof.IsMatch(strBuffer) ) {
// code to follow...
re-position the viewstate and output the altered HTML to the stream.
string finalHtml = _output_buffer.ToString();
int StartPoint = finalHtml.IndexOf("<input type="hidden" name="__VIEWSTATE");
if ( StartPoint >= 0 ) {
int EndPoint = finalHtml.IndexOf("/>", StartPoint) + 2;
string viewstateInput = finalHtml.Substring(StartPoint, EndPoint - StartPoint);
finalHtml = finalHtml.Remove(StartPoint, EndPoint - StartPoint);
int FormEndStart = finalHtml.IndexOf("</form>") - 1;
if ( FormEndStart >= 0 ) {
finalHtml = finalHtml.Insert(FormEndStart, viewstateInput);
}
}
byte[] data = UTF8Encoding.UTF8.GetBytes(finalHtml);
_output_stream.Write(data, 0, data.Length);
Simple as!Now all you need to do us take the full code listing (below) and paste it into a C# file. Then add the following to your web.config inside the
// Source code for IHttpViewstateMover.cs
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
/// <summary>
/// IHttpViewstateMover is a HttpModule that moves the viewstate
/// to the bottom of the HTML source to help with SEO
/// </summary>
public sealed class IHttpViewstateMover : IHttpModule {
// the class is sealed so it cannot be inherited
public void Dispose () {
// nothing to dispose
}
public void Init (HttpApplication context) {
context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);
}
void context_ReleaseRequestState (object sender, EventArgs e) {
HttpResponse response = HttpContext.Current.Response;
// Uncomment the following line if you only want to recieve a single call to ViewstateMover.Write
// context.Response.Buffer = true;
if ( response.ContentType == "text/html" ) {
response.Filter = new ViewstateMover(response.Filter);
}
}
/// <summary>
/// ViewstateMover is the workhorse of the IHttpViewstateMover
/// </summary>
private class ViewstateMover : Stream {
// this class is private as it serves no real purpose outside this implementation
private Stream _output_stream;
private long _position;
private StringBuilder _output_buffer;
/// <summary>
/// Creates a new instance of the ViewstateMover class
/// </summary>
/// <param name="input_stream">The HttpResponse.Filter to work with</param>
public ViewstateMover (Stream input_stream) {
_output_stream = input_stream;
_output_buffer = new StringBuilder();
}
#region Stream Members
public override bool CanRead {
get { return true; }
}
public override bool CanSeek {
get { return true; }
}
public override bool CanWrite {
get { return true; }
}
public override void Close () {
_output_stream.Close();
}
public override void Flush () {
_output_stream.Flush();
}
public override long Length {
get { return 0; }
}
public override long Position {
get { return _position; }
set { _position = value; }
}
public override long Seek (long offset, SeekOrigin origin) {
return _output_stream.Seek(offset, origin);
}
public override void SetLength (long length) {
_output_stream.SetLength(length);
}
public override int Read (byte[] buffer, int offset, int count) {
return _output_stream.Read(buffer, offset, count);
}
#endregion
public override void Write (byte[] buffer, int offset, int count) {
string strBuffer = UTF8Encoding.UTF8.GetString(buffer, offset, count);
// check for the closing HTML tag
Regex eof = new Regex("</html>", RegexOptions.IgnoreCase);
if ( !eof.IsMatch(strBuffer) ) {
_output_buffer.Append(strBuffer);
} else {
_output_buffer.Append(strBuffer);
string finalHtml = _output_buffer.ToString();
// original code from http://www.hanselman.com/blog/MovingViewStateToTheBottomOfThePage.aspx
int StartPoint = finalHtml.IndexOf("<input type="hidden" name="__VIEWSTATE");
if ( StartPoint >= 0 ) {
int EndPoint = finalHtml.IndexOf("/>", StartPoint) + 2;
string viewstateInput = finalHtml.Substring(StartPoint, EndPoint - StartPoint);
finalHtml = finalHtml.Remove(StartPoint, EndPoint - StartPoint);
int FormEndStart = finalHtml.IndexOf("</form>") - 1;
if ( FormEndStart >= 0 ) {
finalHtml = finalHtml.Insert(FormEndStart, viewstateInput);
}
}
byte[] data = UTF8Encoding.UTF8.GetBytes(finalHtml);
// write the page countents out to the user
_output_stream.Write(data, 0, data.Length);
}
}
}
}
As ever, the code is provided as is, with no kind of waranty so please test thoroughly before you place in a production environment. You use this code at your own risk.
Tuesday, 26 February 2008
Shrinking Log files in SQL Server 2005
Here is a quick but of SQL that should help you shrink the file to reclaim some disk space. be warned, this might impeed your ability to restore the database later if it all goes wibble.
First run the following
USE nameOfTheDatabaseHere
SELECT * FROM sysfiles
Now, take note of the fileid of the log file (usualy 2 for most databases) then do
DBCC SHRINKFILE
( fileIDGoesHere, TRUNCATEONLY )
This will truncate the log file to as small as the DB Server will allow.
See http://msdn2.microsoft.com/en-us/library/aa258824.aspx for more info
Wednesday, 20 February 2008
Downloading and Deleting Temporary Files
Once the user had downloaded the file, the zip file needed to be deleted so as not to leave temp files on the servers disk.
I tried a few things like calling File.Delete("path/to/file.zip") after doing Response.TransferFile() or Response.WriteFile() but I found that the page never loaded. I guess it was deleting the file bfore it had chance to stream the file to the client.
Eventually I came up with the code below which reads the entire file into a BinaryWriter and the write it out to the Response's OutputStream. The stream is then flushed and the file can be deleted.
string theFile = "path/to/your.file";
FileInfo theFileInfo = new FileInfo(theFile);
if(theFileInfo.Exists) {
// Clear any output
Response.Clear();
Response.BufferOutput = true;
// should be the MIME-Type of your file
Response.ContentType = "application/x-zip-compressed";
// set the name of the file as it will be downloaded
Response.AddHeader("Content-Disposition", "attachment; filename=the.file");
// Open the OutputStream into a BinaryWriter
BinaryWriter br = new BinaryWriter(Response.OutputStream);
// Read the entire temporary file and write it into the BinaryWriter
br.Write(File.ReadAllBytes(theFileInfo.FullName));
// Flush and Close the Writer
br.Flush();
br.Close();
// Fulsh the Response object
Response.Flush();
// Delete the temporary file
File.Delete(theFileInfo.FullName);
// End the execution of the page
Response.End();
}
While this does get the job done it isn't perfect. The entire file is read into memory before being sent to the client. This means if you are sending large files to many clients at the same time you could have some trouble with the server running out of memory and all manner of other crazy things happening (possibly).
As ever, use at your own risk.
Wednesday, 13 February 2008
SQL : Multiple Order By's
SELECT * FROM tblTableName
WHERE column1='x'
AND column2='y'
ORDER BY column3 ASC, column4 DESC
Nice!(tested in MySQL and MS SQL)
Wednesday, 6 February 2008
Blog code formatting tool
It's not quite what I wanted but I'm not about to write a C# syntax highlighter so it'll do for now
Tuesday, 5 February 2008
ASP.net Image Upload and Resize (in C# .net 2.0, 3.0, 3.5, visual studio 2005, visual studio 2008)
What follows is what I have found to be the simplest and most elegant method of uploading, resizing and saving an image in ASP.NET. So let's get to it.
Ok, lets assume we have a FileUpload control (named fuImageFile) and a Button control (btnUpload) and we're going to upload the image when we click our button. The simplest method of uploading our file might look something like this
protected string savePath = "~/uploaded/";
protected void btnUpload_Click (object sender, EventArgs e) {
string fileName = fuImageFile.FileName;
string saveName = Server.MapPath(savePath) + fileName;
fuImage.SaveAs(saveName);
}
So now we can upload an image to our server, what about resizing that image? For this to work you will need to add a using directive for System.Drawing and System.Drawing.Imaging
using System.Drawing;
using System.Drawing.Imaging;
Next we'll look at how we go about resizing an image (in the form of a Bitmap object) and then at how to integrate that into our upload page.
public Bitmap ResizeBitmap (Bitmap src, int newWidth, int newHeight) {
Bitmap result = new Bitmap(newWidth, newHeight);
using ( Graphics g = Graphics.FromImage((System.Drawing.Image)result) ) {
g.DrawImage(src, 0, 0, newWidth, newHeight);
}
return result;
}
This method takes a Bitmap object and two numbers specifying the height and width of the required image. We then create a new empty Bitmap at the desired size (result) , we then obtain a Graphics object from it (NB: the Graphics object remains associated with the Bitmap) and draw our source image into it.
When we return the result we have an Bitmap object with the image data we drew into the Graphics object.
So now lets work it into our page
protected void btnUpload_Click (object sender, EventArgs e) {
string fileName = fuImageFile.FileName;
// Get the bitmap data from the uploaded file
Bitmap src = Bitmap.FromStream(fuImageFile.PostedFile.InputStream) as Bitmap;
// Resize the bitmap data
Bitmap result = ResizeBitmap (src, 200, 200);
string saveName = Server.MapPath(savePath) + fileName;
result.Save(saveName, ImageFormat.Jpeg);
}
What we do here is take the InputStream of the FileUpload's PostedFile property and create a Bitmap with it, once we have this bitmap object we can call it's Save method to save it to the local disk.Proportional Resizing
The problem with this ResizeBitmap is that it will stretch and pull your input image to fit the dimensions supplied which 99% of the time is not what we will want. We usually want to scale an image keeping its proportions. Take a look at the ProportionallyResizeBitmap method below:
public Bitmap ProportionallyResizeBitmap (Bitmap src, int maxWidth, int maxHeight) {
// original dimensions
int w = src.Width;
int h = src.Height;
// Longest and shortest dimension
int longestDimension = (w>h)?w: h;
int shortestDimension = (w<h)?w: h;
// propotionality
float factor = ((float)longestDimension) / shortestDimension;
// default width is greater than height
double newWidth = maxWidth;
double newHeight = maxWidth/factor;
// if height greater than width recalculate
if ( w < h ) {
newWidth = maxHeight / factor;
newHeight = maxHeight;
}
// Create new Bitmap at new dimensions
Bitmap result = new Bitmap((int)newWidth, (int)newHeight);
using ( Graphics g = Graphics.FromImage((System.Drawing.Image)result) )
g.DrawImage(src, 0, 0, (int)newWidth, (int)newHeight);
return result;
}
This method takes a maxWidth and a maxHeight instead of a newWidth and newHeight, it then does a bit of maths to figure out which is the longest, the original height or the original width, works out the ratio of these two numbers and applies them appropriatley to the target size and resizes the image accordingly.
Just like ResizeBitmap, ProportionallyResizeBitmap returns a Bitmap object so you can simply substitute the call to ResizeBitmap in the button click method and it will all play nicely!
Gotchas
If you get a "Generic Error from GDI +" like Exception Details: System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+ then you should check the following points:
- Make sure the destination folder exists
- Make sure the the local machine user ISS_WPG has write permissions to the destination folder
- Make sure the save path is correctly escaped
See the Microsoft Knowlage Base article http://support.microsoft.com/?id=814675 for more posibilities