Why we use Rails for Client Projects.

Posted by Floyd Price Tue, 06 Jul 2010 17:44:00 GMT

At least 50% of the time a client will want us to use a specific technology (.NET or Java), this makes perfect sense as a lot of our clients are corperates who have invested a lot of time and money in a particular technology.

The great news for us, and the other 50% of our clients is that we choose to use Ruby On Rails whenever possible. The reasons are many, but a few of the more profound ones are:

Productivity

Thats right, we are about 2 (maybe 3) times more productive with Rails than .NET or Java, now this isn't because we are primarily Rails guys in fact I have spent many more years working with both .NET and Java than I have with Rails, the simple fact is that Rails gives us a head start as we get so much for Free.

This is profound in two ways, firstly and most obviously it costs the client less, and enables us to create better relationships. But this productivity gain also allows us to get functionality in front of the user quicker and as such we can identify requirement changes and fix bugs sooner, meaning we deliver better quality code first time.

Agile

We work in an Agile manor and while we can do this regardless of the technology we use, Rails lends itself to an Agile process perfectly.

Solid Design Patterns

Rails encourages the developer to employ consistant design patterns, the rails guys call this Convention over Configuration which promotes maintainable well tested code.

Separation of Concerns

Rails goes beyond Separation of Concerns by removing Concerns, Object Relational Mappers take out 1000's of lines of code that would take up 50% to 80% of the developers time, simple Routing patterns eliminate tones of boiler plate code.

The baked in support for Model View Controller means makes its easy to keep things in the right place.

Open

Over a 10 year contacting career I hit so many hurdles using web frameworks from commercial vendors, from the ASP.NET framework to JSF I found that whenever I wanted to bend these frameworks, they snapped! And the closed source meant that I was back to the drawing board having to invent an ingenues hack, Rails however is open source and the code (especially the rails 3 code) is well written and easy to extend (partly due to the Ruby language), I can easily bend it in any way I choose.

Database Agnostic

As I mentioned the Object Relation Mapper reduces a tone of code and save you even more time, but the abstraction from the database goes even further than that, A rails application written against MYSQL will work against any Database in production, in fact we have an app that is running on SQL Server for one client and Oracle for another, while we host it for other clients on MYSQL.

 

Just a few reasons why we use Rails, I hope you will too.

 


.NET: Converting Word documents (.doc or .docx) to PDF automatically

Posted by Adrian Wed, 09 Sep 2009 14:27:00 GMT

This article contains a brief discussion of the issues and a C# example that you can use to convert Word documents to HTML or PDF on the fly in your applications.

Converting Word documents to PDF and HTML is a vital function for many applications. Opening a Word document requires the user to have Word installed, or at least Word Viewer, and with the advent of IE8 there's no easy way of showing a document in-situ within a web page (you can change the IE settings to get the old behaviour again, but that's too much of an ask for most web apps). The best solution is to convert the document to HTML or PDF, and to store the more portable file alongside the .doc on your server.

The main problem faced by third party converters is that the document needs to be laid out perfectly. It must be absolutely 100% consistent with what the author sees in Word. Any anomalies are unacceptable.

The solution I recommend every time is Word itself. You can automate Word using what are known as interop libraries. These are installed alongside Microsoft Office, so for this to work you must install Office on the server.

Some people will think that installing Office on a production server is unacceptable, or maybe your app runs on a Unix server. There is an answer: create a web service that can be used to retrieve the binary data of the next document to be converted, and accepts the binary data of the converted file. Now you can get a Windows Server, install Office 2007 and deploy a .NET service that constantly polls your web service and performs the conversions as needed. You will get perfect results every time.

Here's sample code that you can use to get up and running straight away. You'll have to make a few tweaks here and there (like the file name), and if you don't already have it you'll need to go to the Microsoft Office web site and download the PDF exporter (luckily it's free).

using Microsoft.Office.Interop.Word;

...

object _read_only = false;
object _visible = true;
object _false = false;
object _true = true;
object _dynamic = 2;
object  _missing = System.Reflection.Missing.Value;

object _htmlFormat = 8;        
object _pdfFormat = 17;
object _xpsFormat = 18;

object fileName = "C:\\Test.docx";

ApplicationClass ac = new ApplicationClass();
//ac.Visible = true; // Uncomment to see Word as it opens and converts the document
//ac.Activate();

Document d = ac.Documents.Open(ref fileName, ref _missing, ref _true, ref _read_only, ref _missing, ref _missing, ref _missing, ref _missing, ref _missing, ref _missing, ref _missing, ref _visible, ref _missing, ref _missing, ref _missing, ref _missing);

object newFileName = ((string)fileName).Substring(0, ((string)fileName).LastIndexOf(".")) + ".pdf";

d.SaveAs(ref newFileName, ref _pdfFormat, ref _missing, ref _missing, ref _missing, ref _missing, ref _missing, ref _missing, ref _missing, ref _missing, ref _missing, ref _missing, ref _missing, ref _missing, ref _missing, ref _missing);

d.Close(ref _false, ref _missing, ref _missing);
ac.Quit(ref _false, ref _missing, ref _missing);

ac = null;

I hope you find this useful. I won't attempt to explain those huge method signatures with all of the _missing parameters, because it isn't important in the context of this example. If you want to know more, I suggest you take a look at the documentation on MSDN -- it's worth reading anyway if you're going to be building Word Interop in to your app.


WPF Scrolling Marque Example (in C#)

Posted by Adrian Thu, 16 Jul 2009 21:28:00 GMT

If you're trying to implement a scrolling marquee in your WPF application, or just programatically moving text and other elements around a canvas, you might find this example useful.

This example requires a Window with nothing more than a Canvas. We've defined this in our XAML file:

<Window x:Class="WpfCanvasTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Component Workshop WPF Marquee Example" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
    <Grid>
    <Canvas x:Name="canvas1" ClipToBounds="True" Width="900" Height="75">
    </Canvas>
  </Grid>
</Window>

All of the action happens in the window's code. This is shown below. You can also download a zip containing the project files at the bottom of this page. There are three major aspects to the code: Adding the TextBlocks to the Canvas (see the code in AddTextBlock, it's nothing special), setting the initial position (this actually happens in the Dispatcher that is initiated in the window's contsructor. We have to do it in the dispatcher because we need the the .NET framework to calculate the widths of our TextBlocks, and this can't happen until we release the thread that we just used to create the TextBlocks). Finally, and the most complicated part of this example is to move each text block left by a certain amount each timer tick. The reason it is complicated is because when a TextBlock drops off the left-hand-side of the screen we remove it from the LinkedList that contains all the TextBlocks, add it to the end of the list and recalculate its position.

The linked list makes the code a little tricker. A simpler implementation might create the TextBlocks in a single StackPanel and then scroll just the panel. When it disappears off the side of the canvas, you could reset it back to the starting position and it'd start over again.

namespace WpfCanvasTest
{
  public partial class Window1 : Window
  {
    const double gap = 100.0; // pixel gap between each TextBlock
    const int timer_interval = 16; // number of ms between timer ticks. 16 is near 1/60th second, for smoother updates on LCD displays
    const double move_amount = 2.5; // number of pixels to move each timer tick. 1 - 1.5 is ideal, any higher will introduce judders

    private LinkedList<TextBlock> textBlocks = new LinkedList<TextBlock>();
    private Timer timer = new Timer();

    public Window1()
    {
      InitializeComponent();

      // A snapshot of today's news (16th July 2009)

      AddTextBlock("Headlines:");
      AddTextBlock("Enhanced Apollo footage released by NASA, original, high quality footage lost");
      AddTextBlock("UK Swine Flu deaths hit 29");
      AddTextBlock("Sport:");
      AddTextBlock("England batsmen struggle in final session on first day of second test against Australia for Ashes");
      AddTextBlock("Owen will be success -- Ronaldo");
      AddTextBlock("Tech:");
      AddTextBlock("Twitter exec's email hacked, stolen documents published on-line");
      AddTextBlock("62% of Sun's shareholders vote to approval Oracle deal");

      canvas1.Dispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(delegate(Object state)
      {
        var node = textBlocks.First;
        
        while (node != null)
        {
          double left = 0;

          if (node.Previous != null)
          {
            Canvas.SetLeft(node.Value, Canvas.GetLeft(node.Previous.Value) + node.Previous.Value.ActualWidth + gap);
          }
          else
          {
            Canvas.SetLeft(node.Value, canvas1.Width + gap);
          }
          
          node = node.Next;
        }

        return null;

      }), null);

      timer.Interval = timer_interval;
      timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
      timer.Start();
    }

    void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
      canvas1.Dispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(delegate(Object state)
      {
        var node = textBlocks.First;
        var lastNode = textBlocks.Last;

        while (node != null)
        {
          double newLeft = Canvas.GetLeft(node.Value) - move_amount;

          if (newLeft < (0 - (node.Value.ActualWidth + gap)))
          {
            textBlocks.Remove(node);

            var lastNodeLeftPos = Canvas.GetLeft(lastNode.Value);

            textBlocks.AddLast(node);

            if ((lastNodeLeftPos + lastNode.Value.ActualWidth + gap)> canvas1.Width) // Last element is offscreen
            {
              newLeft = lastNodeLeftPos + lastNode.Value.ActualWidth + gap;
            }
            else
            {
              newLeft = canvas1.Width + gap;
            }
          }
          
          Canvas.SetLeft(node.Value, newLeft);

          node = node == lastNode ? null : node.Next;
        }

        return null;

      }), null);
    }

    void AddTextBlock(string Text)
    {
      TextBlock tb = new TextBlock();
      tb.Text = Text;
      tb.FontSize = 28;
      tb.FontWeight = FontWeights.Normal;
      tb.Foreground = Brushes.Black;

      canvas1.Children.Add(tb);

      Canvas.SetTop(tb, 20);
      Canvas.SetLeft(tb, -999);

      textBlocks.AddLast(tb);
    }
  }
}

Download the source code and compiled demo.


Setting meaningful version numbers for .Net projects

Posted by Adrian Tue, 14 Jul 2009 14:18:00 GMT

This handy little command line tool (C# source included) will hunt through the folders of your solution looking for AssemblyInfo.cs files. If it finds any, it'll prompt you for a new version number and will then update all values of AssemblyVersion and AssemblyFileVersion with the new value. This makes it very easily to ensure that your version numbers are always meaningful.

A great deal of our primary work involves providing frameworks and libraries that other developers use in their projects. One of the most common problems we face is keeping version numbers meaningful. Visual Studio lets you set a version number in the properties of your project (you open properties in the solution explorer and then click Version Information to do this). Unfortunately it's quite long-winded, especially if you solution spans several projects (or worse still, your project has many solutions).

This little command line tool starts in the current directory and scans through all sub-directories, looking AssemblyInfo.cs files (these are where the properties are stored). If it finds any, if asks you for a new version number and then updates all of the AssemblyInfo.cs files with this new value.

Here's a sample use. I will assume that you've downloaded the tool and saved it to somewhere on your default PATH, for simplicity's sake. Here's a sample console output, showing the tool in use from the command line:

C:\Projects\MyFramework> SetAssemblyVersion.exe
Searching... 

Found 39 AssemblyInfo.cs files. Please specify the new version number:
1.1.0.456
Writing C:\Projects\MyFramework\ServerApi\Properties\AssemblyInfo.cs...
Writing etc...
Done

C:\Projects\MyFramework>

We have adopted a company wide convention for our version numbering scheme that makes it very easy to identify a given DLL or executable, and to know exactly what updates are available and when that DLL was compiled. We number our versions like this:

MajorVersion.Phase.Sprint.SourceCodeRevision

This ties in quite well with most modern enterprise development/project management methodologies, and gives us plenty of information in return.

Download it now: SetAssemblyVersion.exe

For those interested in modifying this tool, here is the source: SetAssemblyVersion.cs. The uncompiled source code is released to the public domain, without restriction, but we'd like it if you got in touch to share any enhancements that you make.

A final note: We don't actually set our version numbers by hand for our largest projects - we use customised msbuild files on our continuous integration server. We'll write another article soon to explain how you can automatically set version numbers before a build using Team City, including using the source repositories revision number as one of the version number components, as explained above.


Basic C#: Converting a string to a proper Enum value

Posted by Adrian Tue, 07 Jul 2009 15:52:00 GMT

This is a very quick beginners tip for those learning .NET. In it, I show you how you can convert between strings, which might be loaded from configuration files or user input, and Enums, that you use to define constants in your application.

First of all, here's a sample enum:

enum Animal { Monkey, Fish, Spider, Pig, Goat }

As you probably know, we use enums like this:

Animal a = Animal.Pig

if (a == Animal.Pig) Oink();

That's a rubbish example, but you get the idea. What if we have the string "Pig", and we need to set our variable based on that? A big if or switch statement would work, but that would add serious maintenance overhead to your application. Instead, we can use Enum.Parse():

Animal a = (Animal)Enum.Parse(typeof(Animal), "Fish");

Enum.Parse returns an object, so we must cast it appropriately. Note also the typeof() first parameter, telling Enum.Parse the type of string it will be trying to decode.

You can also go the other way using just ToString:

Animal a = Animal.Spider

string result = a.ToString(); // result == "Spider"

Configuring log4net at runtime, without XML

Posted by Adrian Tue, 07 Jul 2009 09:05:00 GMT

This quick C# code snippet shows you how you can configure log4net for your application without the need for XML config files. This is useful if you need to enable/disable logging from within the user interface, for example.

Most of this code is quite obvious. The bit that caught me out was the call to ActiveOptions() on the Appender. Here's the code. You need to have a reference to log4net in your project, of course:

log4net.Appender.FileAppender fa = new log4net.Appender.FileAppender();

fa.Name = "LogFile";
fa.AppendToFile = true;
fa.File = "C:\\Sample.log";
fa.LockingModel = new log4net.Appender.FileAppender.MinimalLock();
fa.Layout = new log4net.Layout.PatternLayout("%date [%thread] %-5level %logger - %message%newline");
fa.ImmediateFlush = true;
fa.Threshold = log4net.Core.Level.Warn;
fa.ActivateOptions();

log4net.Config.BasicConfigurator.Configure(fa);

var log = log4net.LogManager.GetLogger("AppName");

log.Error("Yikes!");

Bing: Performing a basic web search over SOAP with the new Bing API 2.0

Posted by Adrian Mon, 06 Jul 2009 11:42:00 GMT

Here's a very quick code sample that you can use to add Bing API search capabilities to your .NET application. You will need to sign-up and get an API key for this to work, but it's free and you can use an existing Live ID if you have one (for example, for MSDN).

The example here was taken from a Console application. You will need to integrate it in to your own application (if you just want to see it working, create your own console application and paste it in to the main function).

You need to add a reference to the SOAP service to your application. Right click the 'References' folder and choose 'Add Service Reference'. The address is: "http://api.bing.net/search.wsdl?Version=2.2&AppID=" with your AppId appended to the end.

string AppId = ""; // enter your AppId key here!
string query = "michael jackson";

using (BingPortTypeClient client = new BingPortTypeClient())
{
  var request = new SearchRequest();

  request.AppId = AppId;
  request.Sources = new SourceType[] { SourceType.Web };
  request.Query = query;

  SearchResponse response = client.Search(request);

  if (response.Web != null && response.Web.Results.Count() > 0)
  {
    var pos = 0;

    foreach (var r in response.Web.Results)
    {
      pos++;

      Console.WriteLine(pos + ". " + r.Title);
      Console.WriteLine(r.Url);
      Console.WriteLine(r.Description);
      Console.WriteLine();
    }
  }
}

Console.ReadLine();

The reason I post this code here is that Microsoft haven't yet updated MSDN with any code samples for the new API yet, and it took me a while to realise that the SOAP client was BingPortTypeClient.

Related: Using the Bing XML Search API with Ruby


Advanced .NET: Storing ViewState in a database

Posted by Adrian Sat, 27 Jun 2009 21:06:00 GMT

There are several ways that you can store viewstate in a database (rather than in a hidden field on the page), but there are very few examples of how to actually do it on the web. Maybe that’s because there aren’t many genuine reasons for changing the default behaviour. You certainly should think twice before changing such a fundamental element of your web applications. This article shows you how to do it if you need to.

Note that this article was originally written in 2007, and has not been tested in recent versions of .NET. Please let me know how you get on using the comments form at the bottom of this page if you use it. Thanks.

There are several ways that you can store viewstate in a database (rather than in a hidden field on the page), but there are very few examples of how to actually do it on the web. Maybe that’s because there aren’t many genuine reasons for changing the default behaviour. You certainly should think twice before changing such a fundamental element of your web applications.

Before ASP.NET 2.0, there was really just one way of achieving what we are about to do; You had to overload two methods in the Page class – LoadPageStateFromPersistenceMedium and SavePageStateToPersistenceMedium. In these methods you would use the exotically named and largely undocumented LosFormatter. This way still works, and you can find examples on Google.

With ASP.NET 2.0 Microsoft introduced a new class, PageStatePersister. By extending this class, we can create our own ViewState persisters. Two such classes already ship – the HiddenFieldPageStatePersister (classic behaviour), and SessionPageStatePersister (stored the same data in Session).

We’re going to create a DatabasePageStatePersister that will store our serialized data in a SQL Server database.

You should be aware that the code I will give you here works, but it is thoroughly untested in the real world.

Our Database

You will need a database, naturally. In this database you will need the following objects.

You will need a table:

CREATE TABLE [dbo].[ViewStateStore]
(
    [guid] [char](128) NOT NULL,
    [viewstatedata] [text] NOT NULL
)

The table should have an index on the guid so that we don’t slow down too much as the table grows:

CREATE NONCLUSTERED INDEX [IDX_Main] ON [dbo].[ViewStateStore] 
(
    [guid] ASC
)

You will also need two stored procuedres:

CREATE PROCEDURE dbo.GetViewState 
(
@guid char(128)
) AS

SET NOCOUNT ON;

SELECT viewstatedata
    FROM ViewStateStore
        WHERE guid = @guid;
CREATE PROCEDURE dbo.StoreViewState 
(
@guid char(128),
@ViewStateData text
) AS

SET NOCOUNT ON;

IF (EXISTS(SELECT 1 FROM ViewStateStore WHERE guid = @guid)) BEGIN

    UPDATE ViewStateStore SET
        viewstatedata = @ViewStateData
        WHERE guid = @guid

END ELSE BEGIN

    INSERT INTO ViewStateStore (guid, viewstatedata)
        VALUES (@guid, @ViewStateData);

END

You must also make sure that you have a database login that can access the database and execute the two procedures.

The Code

We must create a class that extends PageStatePersister.

We will need to provide a constructor taking one parameter (the Page that is creating it), a Load() method and a Save() method. Load and Save are responsible for taking the StateBag and turning it in to a serialized string (and vice-versa).

Because each page’s viewstate is seperate, we must somehow tie the serialized string to the page. For Microsoft’s HiddenElement approach, it isn’t a problem, because the ViewState is intrinsicly tied to the page. For our model, we must ensure that each page has it’s own ViewState that doesn’t interfere with other pages that the user might open (for example, the user is looking at a page that opens a pop-up window—the pop-up window must not interfere with our stored viewstate for the original page).

My solution is to create a GUID in the Page class that is creating the Persister. We shall see this in a second. First, our persister class:

public class DatabasePageStatePersister : PageStatePersister
{
    string _GUID = "";

    public DatabasePageStatePersister(Page p, string GUID) : base(p)
    {
        _GUID = GUID;
    }

    public override void Load()
    {
        string ViewStateData = GetViewState(_GUID);

        this.ViewState = this.StateFormatter.Deserialize(ViewStateData);
    }

    public override void Save()
    {
        string ViewStateData = this.StateFormatter.Serialize(this.ViewState);

        StoreViewState(_GUID, ViewStateData);
    }

    // Database functions ...

}

Our constructor takes a Page and a guid (as a string). The base class constructor will make some associations for us, so we must be careful to call it.

Save() and Load() use the standard helper class StateFormatter to do the hardwork. All we need to do is get/set the values in the database.

Here’s the database code – it should go where the comment is in the extract above.

private SqlConnection _c = new SqlConnection("SERVER=.;DATABASE=ViewState;UID=ViewStateDemo;PWD=ViewStateDemo;");

private void StoreViewState(string guid, string data)
{
    _c.Open();

    try
    {
        SqlCommand cmd = new SqlCommand("StoreViewState", _c);
        cmd.CommandType = CommandType.StoredProcedure;

        cmd.Parameters.Add(new SqlParameter("guid", SqlDbType.Char, 128));
        cmd.Parameters["guid"].Value = guid;

        cmd.Parameters.Add(new SqlParameter("ViewStateData", SqlDbType.Text));
        cmd.Parameters["ViewStateData"].Value = data;

        cmd.ExecuteNonQuery();
    }
    finally
    {
        _c.Close();
    }
}

private string GetViewState(string guid)
{
    string Data = "";

    _c.Open();

    try
    {
        SqlCommand cmd = new SqlCommand("GetViewState", _c);
        cmd.CommandType = CommandType.StoredProcedure;

        cmd.Parameters.Add(new SqlParameter("guid", SqlDbType.Char, 128));
        cmd.Parameters["guid"].Value = guid;

        SqlDataReader r = cmd.ExecuteReader();

        if (r.Read())
        {
            Data = r["viewstatedata"].ToString();
        }
    }
    finally
    {
        _c.Close();
    }

    return Data;
}

Nothing exciting there.

Inside our Page

In the code behind for your page, we must wire up the Persister class that we just created by overloading the property PageStatePersister. Add this code to the body of your code-behind class:

private PageStatePersister _PageStatePersister;

protected override System.Web.UI.PageStatePersister PageStatePersister
{
    get
    {
        if (_PageStatePersister == null)
        {
            string guid = "";

            if (Request["__DATABASE_VIEWSTATE"] == null)
            {
                Guid g = Guid.NewGuid();
                guid = g.ToString();
            }
            else
            {
                guid = Request["__DATABASE_VIEWSTATE"].ToString();
            }

            _PageStatePersister = new DatabasePageStatePersister(this, guid);

            Literal l = new Literal();
            l.Text = "<div><input type=\"hidden\" name=\"__DATABASE_VIEWSTATE\" value=\"" + guid + "\" /></div>";
            this.Form.Controls.Add(l);
        }

        return _PageStatePersister;
    }
}

As you can see, we are changing the behaviour of the page so that the first time that anything tries to access the PageStatePersister variable we will jump in and create an instance of our own class. We also generate a GUID (always guaranteed to be unique) and store this in a hidden element at the end of our form. This is how we link the page request to the data that we stored in the database.

I strongly recommend that the code we created just now for your Page class be placed in its own class (that inherits from System.Web.UI.Page), and that your own webpages inherit from your new class.


Generating SHA1 and MD5 hashes in .NET (C#), Java and Ruby

Posted by Adrian Fri, 26 Jun 2009 21:04:00 GMT

Hashes are a vital technique for validating data that has been passed between two systems. Quite often, the simplest implementation of a hash in one language won't necessarily produce the same hash-string as another language. This article gives you code snippets for three languages that produce identical hashes for any given data.

SHA-1 and MD5 are hashing algorithms. They read some content and produce a string that is relatively unique to that content.

The purpose of a hash is to identify a file as being consistent with your expectations. The two reasons I use a hash are: to ensure that a file I transmit (usually over a web service) is exactly the same as the file on the server, and also to create a ‘base-line’ hash of a downloaded file to compare against the same file at a later date (if the user has made changes the hash will change).

Note that a these hashes, while fairly robust, are not bullet proof. Two files can have the same hash despite being completely different content. These are called collisions, and are extremely rare (at least when considering collisions that happen by chance). Be aware that malicious users can purposefully create matching hashes on different files with relative ease, and this is not intended as a security mechanism (if you need to prove that a document has not changed, consider digital signatures of at least 1024 bytes in length).

The primary purpose for this article is to give programmers a quick reference implementation for the SHA-1 hash that will read a binary file on the local disk and return a hexadecimal string. I have provided implementations for Ruby, Java and .NET that all return identical values for a given file.

If you have written your own functions and are having problems matching your hashes, ensure that you are opening your files in binary mode (applies to Ruby).

Here’s the code:

.NET (C#):

public static string GenerateHash(string filePathAndName)
{
  string hashText = "";
  string hexValue = "";

  byte[] fileData = File.ReadAllBytes(filePathAndName);
  byte[] hashData = SHA1.Create().ComputeHash(fileData); // SHA1 or MD5

  foreach (byte b in hashData)
  {
    hexValue = b.ToString("X").ToLower(); // Lowercase for compatibility on case-sensitive systems
    hashText += (hexValue.Length == 1 ? "0" : "") + hexValue;
  }

  return hashText;
}

Ruby/Rails:

def generate_hash(file_path_and_name)

  hash_func = Digest::SHA1.new # SHA1 or MD5

  open(file_path_and_name, "rb") do |io|
    while (!io.eof)
            readBuf = io.readpartia<script type="text/javascript" src="http://www.componentworkshop.com/javascripts/extensions/tiny_mce/themes/advanced/langs/en.js"></script>l(1024)
            hash_func.update(readBuf)
    end
  end

  hash_func.hexdigest

end

Java:

public static String generateHash(File file) throws NoSuchAlgorithmException, FileNotFoundException, IOException
{
  MessageDigest md = MessageDigest.getInstance("SHA"); // SHA or MD5
  String hash = "";

  byte[] data = new byte[(int)file.length()];
  FileInputStream fis = new FileInputStream(file);
  fis.read(data);
  fis.close();

  md.update(data); // Reads it all at one go. Might be better to chunk it.

  byte[] digest = md.digest();

  for (int i = 0; i < digest.length; i++)
  {
    String hex = Integer.toHexString(digest[i]);
    if (hex.length() == 1) hex = "0" + hex;
    hex = hex.substring(hex.length() - 2);
    hash += hex;
  }

  return hash;
}

Note that all examples use SHA-1 by default, but can easily be changed to use MD5 by changing one line in each case (see comments). Note also that these implementations take a file, but could very easily be adapted to take a byte array, if that's what you're working with.


Versioning a .NET development with Subversion and TortoiseSVN

Posted by Adrian Thu, 18 Jun 2009 20:44:00 GMT
Subversion is the perfect tool for versioning .NET projects. Here I take you through the steps you must follow if you want to use Subversion for your .NET Project.

I will assume that you already have a working Subversion repository to hold your project (if not, take a look at our managed hosting platform CodeSpaces!)

I am going to explain the process of creating a .NET solution from scratch and adding it to subversion. It is easy enough to adapt these instructions and use them for existing projects.

Create the Project Files

First of all, we create an empty solution in Visual Studio (File -> New -> Project..., Other Project Types, Visual Studio Solutions, Blank Solution). You must provide as path for your solution (I use C:\Development) and a name. In this example, I have called my solution ProjectX and my folder is C:\Development.

I will create two new sub-projects in my solution. One will be a class library, and one will be a web application. Still in Visual Studio, right click on the solution in the solution explorer and choose "Add -> New Project...". I have created two projects called Model and Website. If you need to configure references or include any 3rd party DLLs, you can do that now (if I use 3rd party components, I typically create a folder called Libraries in my solution folder -- I.E., C:\Development\ProjectX\Libraries, so that the DLLs are source controlled along with the source code).

Before we add our project to Subversion, we want to make sure that we don’t check in folders that contain binary output. Such files and folders change every single time we compile, and thus become meaningless noise if they appear in every single commit.

You should close Visual Studio, and then delete the .sou file that it has created in the solution folder. You should also delete any bin or obj folders that have been created in the sub-project folders (if you built or ran the solution).

First commit

Having deleted these files and folders, we are ready to commit. Right click the solution folder (ProjectX, in my case) and choose TortoiseSVN -> Import

I always create a 'trunk' folder in the root of my repository. This is a convention that is widely adopted -- primary development happens to code in the trunk and you create branch and tag folders when you need a snapshot of development at a point in time. In the import window, if you append trunk to the url of your repository, the folder will be created for you. My repository url for the import is:

http://svn.codespaces.com/example/projectx/trunk

Click OK, and your files are added to the repository.

Getting a working copy

This is an important step. You should now move or rename your project folder to another location, and get a new, working copy from Subversion. If you miss this step out and make changes to the folder and files that you just imported, you will not be able to commit those changes!

Once you have deleted, moved or renamed the project folder, you should create an empty folder of the same name.

Now right click the empty folder and choose ‘SVN Checkout’. The url should be correct already. If not, use the url that you entered above during the import.

Click OK and your folder will be populated with the project files you just added to Subversion. The icons should have little green ticks to indicate that they are unchanged from the versions in Subversion.

Cleaning up, again

Now re-open your solution in Visual Studio and compile everything (or run the application). When you have done this, close the solution and go back to Windows Explorer. This will cause bin and obj folders to be created for your projects, and an suo file will appear in the project's top folder.

We’re going to use Tortoise to update the properties on several folders to ignore these files, but first we must first right click the solution folder and choose SVN Update. It will say “completed at version 1” without actually doing anything. It is important that we do this, before updating properties (though I am not sure why). If you don't Update first, your next commit (with the ignore commands) will fail.

Right click the solution folder and choose SVN Commit. The commit window will appear. Don’t click OK yet.

You can right-click on the files in this window and perform certain actions. You will need to right click the .sou file and choose 'Add To Ignore List -> FileName.sou' (where FileName is the name of the solution It will disappear from the list.

Now you need to do exactly the same thing for all of the bin and obj folders only (not their contents, just the bin and obj folders!). Right click them, and choose Add To Igore List -> bin/obj

When this is done you will see that the project root-folder (.) and the sub-project folders are identified as being modified. This is because we have just set their properties to ignore those selected files and folders. When we commit, those properties will be written back to the server. Click OK and it should say “Completed at version 2”.

Your solution is now ready for development.

Working in a team

All developers on the team will need to checkout the source from the subversion repository.

When a developer is ready to commit, they must first run SVN Update on their local copy of solution. This fetches all changes made since their last update. You don’t need to close Visual Studio to do this, but you might get notices that files have changed if you don’t.

SVN Update can identify and often resolve conflicts (where two developers change the same file). Sometimes, it is unable to automatically resolve conflicts. These occurances are rare. The supplied TortoiseSVN tools are excellent, and make it clear where the problems are. If the conflict is not easy to resolve, it is important that the developers can sit together to go through the changes and choose which stay, which go, or how best to merge. To merge, you should locate the conflict area in the bottom most window panel and right click the conflicted block. You can choose from theirs, mine, theirs before mine etc. Once done, click the little ‘resolved’ icon (an explanation mark) and then the save the file. This might take some practice to get right, but it's generally straight forward.

The developer can now commit. However, before doing so, it is good practice to double check that the project still builds and that unit tests still pass after all other changes are merged.

Once you are familiar with these steps, the process of updating and committing becomes quite a rapid and exceptionally useful exchange. Because a developer's update is applied in a single transaction, we know that the files that have changed are related to just one area of functionality. Thus, to perform an update and find that we can no longer compile is not a serious problem – tracking down the changes is very easy indeed. Of course, the longer the other developers wait between Updating their own projects (you don’t need to do it just before a commit, you can do it as often as need be) the more changes will be rolled in to one update, but it is still extremely useful and a world away from the lock -> update -> release mind-set of Source Safe.


About

We are a small British company that produces business-oriented software and solutions. These articles are a product of our daily work - information that we think might be useful to share. We hope you find them useful.

Our Software

These are some of our products. Several are open source, some are web-based and others are proprietary:

Categories

Archives

Syndicate

ml> ._trackPageview(); } catch(err) {} ml> l> pageTracker._trackPageview(); } catch(err) {} ml> ._trackPageview(); } catch(err) {} ml> l>