private bool ValidateDgvAddServices()
        {
            if (dgvAddServices.Rows.Count == 1 && dgvAddServices.Rows[0].IsNewRow == true)
            {
                MessageBox.Show("Please add one or more services to the list.", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                return(false);
            }

            foreach (DataGridViewRow serviceRow in dgvAddServices.Rows)
            {
                if (serviceRow.IsNewRow == false)
                {
                    // Service Title
                    object cellValue = serviceRow.Cells[0].Value;
                    if ((cellValue == null) || (cellValue.ToString().Trim() == String.Empty))
                    {
                        MessageBox.Show("Please provide a service title for row " + serviceRow.Index.ToString(),
                                        this.Text, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                        return(false);
                    }

                    // Service URL
                    cellValue = serviceRow.Cells[1].Value;
                    if ((cellValue == null) || (cellValue.ToString().Trim() == String.Empty))
                    {
                        MessageBox.Show("Please provide a service URL for row " + serviceRow.Index.ToString(),
                                        this.Text, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                        return(false);
                    }
                    // Trim the query off of the URL
                    string serviceUrl = cellValue.ToString().Trim();
                    try
                    {
                        serviceUrl = WebOperations.GetCanonicalUri(serviceUrl, true);
                    }
                    catch
                    {
                        MessageBox.Show("Please provide a service URL for row " + serviceRow.Index.ToString(),
                                        this.Text, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                        return(false);
                    }
                }
            }

            return(true);
        }
        /// <summary>
        /// Searches for WaterOneFlow service info in a DataTable, and adds info about those services to the data grid view
        /// </summary>
        /// <param name="pathToFile">Path to CSV file</param>
        /// <param name="e">Parameters from the BackgroundWorker</param>
        /// <returns>Parameters (task type, output message, rows to add to view) to be processed by a BackgroundWorker event handler</returns>
        private object[] AddServicesFromDataTable(string pathToFile, DoWorkEventArgs e)
        {
            // Build parameters to pass to the background worker
            object[] parameters = new object[3];
            parameters[0] = BackgroundWorkerTasks.AddServicesFromFile;
            parameters[1] = "Operation cancelled";

            // Read the CSV file into a DataTable
            bgwMain.ReportProgress(0, "Opening file, please wait...");

            DataTable dataTable = null;

            try
            {
                dataTable = CsvFileParser.ParseFileToDataTable(pathToFile, true);
            }
            catch (Exception ex)
            {
                throw new Exception("Could not read file. " + ex.Message);
            }

            // Get the columns from the table
            int colTitle    = dataTable.Columns.IndexOf("Title");
            int colUrl      = dataTable.Columns.IndexOf("URL");
            int colCode     = dataTable.Columns.IndexOf("Code");
            int colCitation = dataTable.Columns.IndexOf("Citation");
            int colAbstract = dataTable.Columns.IndexOf("Abstract");
            int colWebsite  = dataTable.Columns.IndexOf("Website");
            int colName     = dataTable.Columns.IndexOf("Contact");
            int colEmail    = dataTable.Columns.IndexOf("Email");

            if (colUrl == -1)
            {
                throw new Exception("URL column not found in CSV file");
            }

            // Find items with an element providing the URL to a WaterOneFlow service
            int totalSteps  = dataTable.Rows.Count;
            int currentStep = 0;

            List <string[]> rowsToAdd = new List <string[]> ();

            foreach (DataRow dataRow in dataTable.Rows)
            {
                // Update progress
                if (bgwMain.CancellationPending)
                {
                    e.Cancel = true;
                    return(parameters);
                }

                currentStep++;
                bgwMain.ReportProgress(100 * currentStep / totalSteps, "Searching for WaterOneFlow service info: " + currentStep + " of " + totalSteps + "...");

                // Build service info from the row
                string title = "";
                if (colTitle != -1)
                {
                    title = dataRow[colTitle].ToString();
                }
                string url = "";
                if (colUrl != -1)
                {
                    url = dataRow[colUrl].ToString();
                    try
                    {
                        url = WebOperations.GetCanonicalUri(url, true);
                    }
                    catch
                    {
                        url = "";
                    }
                }
                string code = "";
                if (colCode != -1)
                {
                    code = dataRow[colCode].ToString();
                }
                string citation = "";
                if (colCitation != -1)
                {
                    citation = dataRow[colCitation].ToString();
                }
                string serviceAbstract = "";
                if (colAbstract != -1)
                {
                    serviceAbstract = dataRow[colAbstract].ToString();
                }
                string website = "";
                if (colWebsite != -1)
                {
                    website = dataRow[colWebsite].ToString();
                }
                string name = "";
                if (colName != -1)
                {
                    name = dataRow[colName].ToString();
                }
                string email = "";
                if (colEmail != -1)
                {
                    email = dataRow[colEmail].ToString();
                }

                // Create an item to add to the data grid view
                if (url != String.Empty)
                {
                    string[] row = { title, url, code, citation, serviceAbstract, website, name, email };

                    rowsToAdd.Add(row);
                }
            }

            // Prepare a message to the user
            string message       = "";
            int    servicesAdded = rowsToAdd.Count;

            if (servicesAdded == 0)
            {
                message = "No services found in file";
            }
            else if (servicesAdded == 1)
            {
                message = "1 service found in file";
            }
            else
            {
                message = servicesAdded.ToString() + " services found in file";
            }

            parameters[1] = message;
            parameters[2] = rowsToAdd;

            return(parameters);
        }