Monday, December 10, 2012

Restoring a LocalDB within an MVC web application

UPDATE: EntityFramework 6 has lots of Resiliency enhancements, but one of the side effects is that this needs a tweak to keep EF from spinning up a transaction around the SQL statement.  Essentially, you have to call ExecuteSqlCommand and request that it does NOT ensure the a transaction exists with the first parameter of TransactionalBehavior.DoNotEnsureTransaction.  If still running EF 5 or below, omit that argument. 

So, as a follow-up to backing up a LocalDB database, I guess I should show the simplest path to restoring one.

So, without further adéu, I give you:

public class RestoreDatabaseModel
    {
        public HttpPostedFileBase File { get; set; }
    }

        //
        // GET: /Admin/RestoreDatabase
        [Authorize(Roles = "Admin")]
        public ActionResult RestoreDatabase()
        {
            return View(new RestoreDatabaseModel());
        }

        //
        // POST: /Admin/RestoreDatabase
        [Authorize(Roles = "Admin")]
        [HttpPost]
        public ActionResult RestoreDatabase(RestoreDatabaseModel model)
        {
            const string YOURAPPNAME = "YourAppName";
            var dbPath = Server.MapPath(String.Format("~/App_Data/Restore_{0}_DB_{1:yyyy-MM-dd-HH-mm-ss}.bak", YOURAPPNAME, DateTime.UtcNow));

            try
            {
                model.File.SaveAs(dbPath);

                using (var db = new DBContext())
                {
                    var cmd = String.Format(@"
USE [Master]; 
ALTER DATABASE {0} SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
RESTORE DATABASE {0} FROM DISK='{1}' WITH REPLACE;
ALTER DATABASE {0} SET MULTI_USER;"
                        , YOURAPPNAME, dbPath);
                    db.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, cmd);
                }

                 ModelState.AddModelError("", "Restored!");
            }
            catch (Exception ex)
            {
                ModelState.AddModelError("", ex);
            }

            return View(model);
        }
This iteration saves the posted file based on the current date-time and the supplies the correct commands to restore the database. I leave the flushing of HttpCache to you...

Also, if you haven't extended the upload limits of a POST, you'll need this (or similar) in your web.config
<system.web>
    <httpRuntime maxRequestLength="40960" targetFramework="4.5">
    </httpRuntime>
</system.web>
This enables larger files to be uploaded (in this case, 40MB... if your database backup is bigger than that, you have no business hacking around with a LocalDB... get a real SQL Server instance to point at.

Tuesday, December 04, 2012

How to create random readable strings for .Net application

Why would I want to be random?

If you need a random string, I assume you know why you're here. However there are some common uses for random strings I want to list out for the Google juice factor:
  1. CAPTCHA codes when not using something cool like reCAPTCHA
  2. Email verification codes.
  3. Nonce values for challenge/response.
  4. salt values to increase entropy on password hashes.
  5. Registration codes.

How should I generate them in .Net?

There is a simple answer, really. In .Net you can just make a call to RNGCryptoServiceProvider's GetNonZeroBytes method and convert those bytes to characters.
var random = new byte[16];           // whatever size you want
var rng = new RNGCryptoServiceProvider();
rng.GetNonZeroBytes(random);         // Fill with non-zero random bytes

return Convert.ToBase64String(random);  // convert to a string.
If you have the MVC 4 package available, you can use the convenient Crypto.GenerateSalt method as a shorthand as it essentially does the above code.

This, of course, limits the returned string to the Base-64 characters.

When should I care about the contents?

In general, you don't care about the contents of the random string. The one generated by logic above is pretty useful as it is a wide set of all-ASCII characters that will not get you in trouble when crossing code-pages.

The biggest downside of this approach is that the string is only using the a 64 character set, so you're excluding a lot of other possible characters, but in most applications that isn't a problem.  In fact, quite the opposite is true. In many cases, we might want to avoid specific characters like the + character  because this might be used in a URL In other cases, you might want to generate a fuller character set (or a specific set  like an all-emoji string).

A more common need, though, would be if you need to put something on screen for a user to type (such as a registration code) that should not be easy to mistake characters.  In some fonts, the characters 1, l and I or 0, o and 0 are very easily mistaken. For such cases, you can use a function like the following to generate a reasonably readable string
namespace Silly
{
    using System.Security.Cryptography;

    public static partial class Helpers
    {
        public static string RandomReadableString(int length)
        {
            return "23456789ABCDEFGHJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz".RandomString(length);
        }

        public static string RandomString(this string characterSet, int length)
        {
            var rng = new RNGCryptoServiceProvider();
            var random = new byte[length];
            rng.GetNonZeroBytes(random);

            var buffer = new char[length];
            var usableChars = characterSet.ToCharArray();
            var usableLength = usableChars.Length;

            for (int index = 0; index < length; index++)
            {
                buffer[index] = usableChars[random[index] % usableLength];
            }

            return new string(buffer);
        }
    }
}
You can call the second function against any string of characters. For example I'm using the RandomReadableString method to generate email confirmation codes that can easily be typed if needed.

Boring! Spice it up...

For even more fun, here's some Emoji sequences that can be used for eye charts or stupid pet code tricks.
// Emoji fun
// random weather "☀☁☂☃"
// random finger pointers "☜☝☞☟"
// random zodiac "♈♉♊♋♌♍♎♏♐♑♒♓"
// random chess pieces "♔♕♖♗♘♙♚♛♜♝♞♟"
// random music notation "♩♪♫♬♭♯"
// random trigrams "☰☱☲☳☴☵☶☷"
// random planets "♃♄♅♆♇"

Tuesday, November 27, 2012

How to backup a LocalDB database under an MVC 4 sytem

UPDATE: EntityFramework 6 has lots of Resiliency enhancements, but one of the side effects is that this needs a tweak to keep EF from spinning up a transaction around the SQL statement.  Essentially, you have to call ExecuteSqlCommand and request that it does NOT ensure the a transaction exists with the first parameter of TransactionalBehavior.DoNotEnsureTransaction.  If still running EF 5 or below, omit that argument. 

I have a smallish MVC 4 site with a database. In this case it isn't worthy of a dedicated SQL Server, so I decided to try out the new LocalDb database feature.

While the database isn't particularly mission critical, I would like to be able to easily back it up on demand to allow some level of disaster recovery.

So, without further adéu, I give you:

namespace SomeSimpleProject.Controllers
{
    [Authorize(Roles="Admin")]
    public class BackupController : Controller
    {
        public ActionResult BackupDatabase()
        {
            var dbPath = Server.MapPath("~/App_Data/DBBackup.bak");
            using (var db = new DbContext())
            {
                var cmd = String.Format("BACKUP DATABASE {0} TO DISK='{1}' WITH FORMAT, MEDIANAME='DbBackups', MEDIADESCRIPTION='Media set for {0} database';"
                    , "YourDB", dbPath);
                db.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, cmd);
            }
       
            return new FilePathResult(dbPath, "application/octet-stream");
        }
    }
}