private void PostCsv()
        {
            var now      = DateTime.UtcNow;
            var messages = new List <string>();
            var good     = 0;
            var bad      = 0;

            try
            {
                if (Request.Files.Count != 1 || Request.Files[0].ContentLength == 0)
                {
                    throw new VoteException("Could not find CSV file");
                }
                using (var parser = new TextFieldParser(Request.Files[0].InputStream, Encoding.UTF8))
                {
                    parser.TextFieldType             = FieldType.Delimited;
                    parser.HasFieldsEnclosedInQuotes = true;
                    parser.SetDelimiters(",");
                    // look for the field names -- they aren't the first row so find a row whose
                    // first column is "FirstName"

                    string[] columnNames = null;
                    while (!parser.EndOfData)
                    {
                        var row = parser.ReadFields();
                        // ReSharper disable once PossibleNullReferenceException
                        if (row.Length > 0 && row[0] == "FirstName")
                        {
                            columnNames = row;
                            break;
                        }
                    }

                    if (columnNames == null)
                    {
                        throw new VoteException("Could not find column names row (\"FirstName\" in first column");
                    }
                    var maxColumnInx       = -1;
                    var firstNameInx       = GetColumnIndex(columnNames, "FirstName", ref maxColumnInx);
                    var lastNameInx        = GetColumnIndex(columnNames, "LastName", ref maxColumnInx);
                    var address1Inx        = GetColumnIndex(columnNames, "Address1", ref maxColumnInx);
                    var address2Inx        = GetColumnIndex(columnNames, "Address2", ref maxColumnInx);
                    var cityInx            = GetColumnIndex(columnNames, "City", ref maxColumnInx);
                    var stateProvinceInx   = GetColumnIndex(columnNames, "StateProvince", ref maxColumnInx);
                    var zipCodeInx         = GetColumnIndex(columnNames, "ZipCode", ref maxColumnInx);
                    var emailInx           = GetColumnIndex(columnNames, "Email", ref maxColumnInx);
                    var phoneInx           = GetColumnIndex(columnNames, "Phone", ref maxColumnInx);
                    var transactionDateInx = GetColumnIndex(columnNames, "TransactionDate", ref maxColumnInx);
                    var totalChangedInx    = GetColumnIndex(columnNames, "TotalCharged", ref maxColumnInx);

                    while (!parser.EndOfData)
                    {
                        var row = parser.ReadFields();
                        try
                        {
                            // ReSharper disable once PossibleNullReferenceException
                            if (row.Length <= maxColumnInx)
                            {
                                throw new VoteException($"Contains only {row.Length} columns, {maxColumnInx + 1} required.");
                            }

                            var email = row[emailInx];
                            if (string.IsNullOrWhiteSpace(email))
                            {
                                throw new VoteException("Email is missing");
                            }
                            if (!Validation.IsValidEmailAddress(email))
                            {
                                throw new VoteException($"Invalid Email: {email}");
                            }

                            var firstName = row[firstNameInx];
                            var lastName  = row[lastNameInx];
                            var fullName  = firstName + " " + lastName;
                            if (string.IsNullOrWhiteSpace(fullName))
                            {
                                throw new VoteException("FirstName or LastName is missing");
                            }

                            var address  = row[address1Inx];
                            var address2 = row[address2Inx];
                            if (!string.IsNullOrWhiteSpace(address) && !string.IsNullOrWhiteSpace(address2))
                            {
                                address += ", " + address2;
                            }

                            var city = row[cityInx];
                            if (string.IsNullOrWhiteSpace(city))
                            {
                                throw new VoteException("City is missing");
                            }

                            var stateCode = row[stateProvinceInx];
                            if (string.IsNullOrWhiteSpace(stateCode))
                            {
                                throw new VoteException("StateProvince is missing");
                            }
                            if (!StateCache.IsValidStateCode(stateCode))
                            {
                                // might be state name
                                stateCode = StateCache.GetStateCode(stateCode);
                                if (!StateCache.IsValidStateCode(stateCode))
                                {
                                    throw new VoteException("Invaid state or state code");
                                }
                            }

                            var zipCode = row[zipCodeInx];
                            if (string.IsNullOrWhiteSpace(zipCode))
                            {
                                NonFatalError(messages, parser.LineNumber, $"ZipCode is missing ({email})");
                            }
                            var zipMatch = Regex.Match(zipCode, @"(?<zip5>\d{5})(?:\D?(?<zip4>\d{4}))?");
                            var zip5     = string.Empty;
                            var zip4     = string.Empty;
                            if (!zipMatch.Success)
                            {
                                NonFatalError(messages, parser.LineNumber, $"Could not parse ZipCode: {zipCode} ({email})");
                            }
                            else
                            {
                                zip5 = zipMatch.Groups["zip5"].Value;
                                zip4 = zipMatch.Groups["zip4"].Value;
                            }

                            var phone = row[phoneInx].NormalizePhoneNumber();

                            DateTime transactionDate;
                            if (!DateTime.TryParse(row[transactionDateInx], out transactionDate))
                            {
                                throw new VoteException($"Could not parse TransactionDate: {row[transactionDateInx]}");
                            }

                            decimal totalChanged;
                            if (!decimal.TryParse(row[totalChangedInx], out totalChanged))
                            {
                                throw new VoteException($"Could not parse TotalCharged: {row[totalChangedInx]}");
                            }

                            if (Donations.EmailDateExists(email, transactionDate))
                            {
                                throw new VoteException(
                                          "A donation for this email, date and time already exists" +
                                          $" ({email}, {transactionDate:G}, {totalChanged:C})");
                            }
                            Donations.Insert(email, transactionDate, firstName, lastName, fullName,
                                             address, city, stateCode, zip5, zip4, phone, totalChanged, false);

                            // Get the encoding
                            var input = address + " " + city + " " + stateCode + " " + zip5;
                            if (!string.IsNullOrWhiteSpace(zip4))
                            {
                                input += "-" + zip4;
                            }
                            var result = AddressFinder.Find(input, null, false);
                            if ((result.Congress != null) && (result.Congress.Length == 3))
                            {
                                result.Congress = result.Congress.Substring(1);
                            }
                            var table = Addresses.GetDataByEmail(email);
                            if (table.Count == 0) // Insert
                            {
                                Addresses.Insert(firstName, lastName, address,
                                                 city, stateCode, zip5, zip4, email,
                                                 phone, now, "DONR", false, false, false, DefaultDbDate, string.Empty,
                                                 result.Congress.SafeString(), result.StateSenate.SafeString(),
                                                 result.StateHouse.SafeString(), result.County.SafeString(),
                                                 result.Success ? now : DefaultDbDate, 0, DefaultDbDate, true);
                            }
                            else if (result.Success) // update all matching Addresses
                            {
                                foreach (var r in table)
                                {
                                    if (!string.IsNullOrWhiteSpace(firstName))
                                    {
                                        r.FirstName = firstName;
                                    }
                                    if (!string.IsNullOrWhiteSpace(lastName))
                                    {
                                        r.LastName = lastName;
                                    }
                                    if (!string.IsNullOrWhiteSpace(phone))
                                    {
                                        r.Phone = phone;
                                    }
                                    r.IsDonor = true;
                                    if (!string.IsNullOrWhiteSpace(result.Congress))
                                    {
                                        r.Address               = address;
                                        r.City                  = city;
                                        r.StateCode             = stateCode;
                                        r.Zip5                  = zip5;
                                        r.Zip4                  = zip4;
                                        r.CongressionalDistrict = result.Congress;
                                        r.StateSenateDistrict   = result.StateSenate;
                                        r.StateHouseDistrict    = result.StateHouse;
                                        r.County                = result.County;
                                        r.DistrictLookupDate    = now;
                                    }
                                }
                                Addresses.UpdateTable(table);
                            }

                            messages.Add(
                                $"<p>{totalChanged:C} donation added for {fullName}&lt;{email}&gt; on {transactionDate:G}</p>");
                            good++;
                        }
                        catch (Exception ex)
                        {
                            messages.Add(
                                $"<p class=\"error\">Error on row {parser.LineNumber}: {ex.Message}</p>");
                            bad++;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                messages.Add(
                    $"<p class=\"error\">Error: {ex.Message}</p>");
                bad++;
            }
            messages.Add($"<p>{good} donations added. {bad} errors.</p>");
            SummaryPlaceHolder.Controls.Add(new LiteralControl(string.Join(string.Empty, messages)));
            SummaryContainer.RemoveCssClass("hidden");
        }