Validation of ISBN Number in C#.

If you have ever had to work with bibliographical data you'll soon realise how important it is to have absolutely valid data.

This is where the following code will come in useful, it is a Visual Studio 2003 solution written in C# using the .NET CLR Runtime version 1.1. I have included the code of the main class on this page (below) and also a link to download the entire solution. I have also included a test class for you NUnit junkies!

You will probably want to look at the help files for the ISBN validation algorithm and project, imageto be found here. There is also a compiled HTML help file (CHM) imageto be found here. All thanks to the magic of NDoc.

You can imagedownload the whole project here.

using System;
     using System.Text.RegularExpressions;
   
namespace ISBN
     {
   /// <summary>
   /// ISBNNumber implements a class which will validate an ISBN number.
   /// </summary> 
   /** <remarks>ISBNs are composed of thirteen characters, limited to the number
   characters "0" through "9", the hyphen, and the letter "X". This thirteen-
   character code is divided into four parts, each separated by hyphens:
   group identifier, publisher identifier, book identification for the
   publisher, and the check digit. The first part (group identifier) is used
   to identify countries, geographical regions, languages, etc. The second
   part (publisher identifier) uniquely identifies the publisher. The third
   part (book identifier) uniquely identifies a given book within a
   publisher's collection. The fourth and final part (check digit) is used
   with the other digits in the code in an algorithm to derive a verifiable
   ISBN. The number of digits in the first three parts of an ISBN may contain
   a variable number of digits, but the check digit will always consist of a
   single character (between "0" and "9", or "X" for a value of 10) and the
   ISBN as a whole will always consists of thirteen characters (ten numbers
   plus the three hyphens dividing the four parts of the ISBN).
 <br />
   This version does not separate on hyphens and discards all hyphens and other non-valid characters.
 </remarks>
   */
   public class ISBNNumber {
 #region Members
   private string lastDigit =null;
   private string m_ISBN = null;
   #endregion
 #region Constructors
 /// <summary>
   /// Constructor, for use without passing the ISBN Number.</summary>
   /// <code>ISBN.ISBNNumber in = new ISBN.ISBNNumber();</code>
   /// <remarks>It is preferable to use the alternative 
   /// constructor.<see cref="ISBNNumber"/></remarks>
   public ISBNNumber() {}
   /// <summary>
   /// Constructor, accepts an ISBN Number.</summary>
   /// <code>ISBN.ISBNNumber in = new ISBN.ISBNNumber("3-88053-002-5");</code>
   /// <remarks>Will throw either ArgumentNullException or ArgumentOutOfRangeException.</remarks>
   /// <exception cref="System.ArgumentNullException">Thrown when instantiated with
   /// a null object.</exception>
   /// <exception cref="System.ArgumentOutOfRangeException">Thrown when 
   /// instantiated with a badly formatted ISBN number.</exception>
   /// <param name="ISBN">The candidate ISBN number.</param>
   public ISBNNumber(string ISBN) {
   this.ISBN=ISBN;
   }
   #endregion
   
 /// <summary>
   /// IsValid property. </summary>
   /// <value>
   /// Returns true if the ISBN number is of a valid format (10 characters, last one may be an X)
   /// and if the ISBN number has a valid checksum.</value>
   /// <remarks>An ISBN can be verified to be a valid code using a simple mathematical
   /// algorithm. This algorithm takes each of the nine single digits from the
   /// first three parts of the ISBN (sans the non-numeric hyphens), multiplies
   /// each single digit by a number that is less than eleven the number of
   /// positions from the left each digit that is in the ISBN, adds together the
   /// result of each multiplication plus the check digit, and then divides that
   /// number by eleven. If that division by eleven results in no remainder
   /// (i.e., the number is modulo 11), the candidate ISBN is a valid ISBN.
   /// </remarks>
   public bool IsValid{
   get {
   
   if(m_ISBN == null){
   return false;
   }
 int sum = 0;
   int i=1;
   for (i=1;i<10;i++)
   {
   sum += Convert.ToInt16(this.m_ISBN.Substring(i-1,1)) * (11 - i);
   }
   if(this.lastDigit.ToUpper().Equals("X"))
   sum += 10;
   else
   sum += Convert.ToInt16(this.lastDigit);
 return ((sum % 11) == 0);
   }
   }
 #region ISBN Number
   /// <summary>
   /// The ISBN number to be validated.
   /// </summary> 
   /// <remarks>Will throw either ArgumentNullException or ArgumentOutOfRangeException.</remarks>
   /// <exception cref="System.ArgumentNullException">Thrown when instantiated with a 
   /// null object.</exception>
   /// <exception cref="System.ArgumentOutOfRangeException">Thrown when 
   /// instantiated with a badly formatted ISBN number.</exception>
   /// <value>The 10 character ISBN code. Any extraneous characters are stripped.</value>
   public String ISBN {
   get {
   return m_ISBN + lastDigit;
   }
   set {
 if(value == null)
   {
   throw new ArgumentNullException("ISBN","Don't feed me null values!");
   }
 if(value.Length < 10) {
   throw new ArgumentOutOfRangeException("ISBN",value,
 "ISBN must have 10 characters, but " + value + " actually has only " + value.Length +" characters.");
   }
 //Get rid of any non ISBN characters, 
   //First add only digits but not the last one to a temp string
   m_ISBN = Regex.Replace(value.Substring(0,value.Length-1).Trim().ToUpper(), @"[^\d]", "");
   //then add the last character if either a digit or an x
   lastDigit = Regex.Replace(value.Substring(value.Length-1,1).Trim().ToUpper(), @"[^\dxX]", "");
   
   //must be 10 characters long
   if(this.ISBN.Length!=10) {
   throw new ArgumentOutOfRangeException("ISBN",m_ISBN,
 "ISBN must have 10 characters, but " + this.ISBN + " actually has " + this.ISBN.Length +" valid characters.");
   }
   }
   }
   #endregion
 }
   
}