public static string SaveChanges(string rows)
    {
        Dictionary <string, string> result = new Dictionary <string, string>()
        {
            { "saved", "" }, { "ids", "" }, { "error", "" }
        };
        bool   saved = false;
        string ids = string.Empty, errorMsg = string.Empty, tempMsg = string.Empty;

        try
        {
            DataTable dtjson = (DataTable)JsonConvert.DeserializeObject(rows, (typeof(DataTable)));
            if (dtjson.Rows.Count == 0)
            {
                errorMsg = "Unable to save. An invalid list of changes was provided.";
                saved    = false;
            }

            int    id = 0;
            string title = string.Empty, description = string.Empty
            , lastMeeting = string.Empty, nextMeeting = string.Empty, devStart = string.Empty;
            int priorityID = 0, smeID = 0, leadIATWID = 0, leadResourceID = 0, submittedByID = 0;
            int td = 0, cd = 0, c = 0, it = 0, cvt = 0, adopt = 0, cr = 0, archive = 0;
            int hasSlides = 0, workStoppage = 0;

            //save
            foreach (DataRow dr in dtjson.Rows)
            {
                id             = 0;
                title          = string.Empty;
                description    = string.Empty;
                archive        = 0;
                lastMeeting    = string.Empty;
                nextMeeting    = string.Empty;
                devStart       = string.Empty;
                smeID          = 0;
                leadIATWID     = 0;
                leadResourceID = 0;
                submittedByID  = 0;

                tempMsg = string.Empty;
                title   = dr["TITLE"].ToString();
                if (string.IsNullOrWhiteSpace(title))
                {
                    tempMsg = "You must specify a value for MS.";
                    saved   = false;
                }
                else
                {
                    int.TryParse(dr["WORKREQUESTID"].ToString(), out id);
                    description = dr["DESCRIPTION"].ToString();
                    lastMeeting = dr["Last_Meeting"].ToString();
                    nextMeeting = dr["Next_Meeting"].ToString();
                    devStart    = dr["Dev_Start"].ToString();
                    int.TryParse(dr["PRIORITY"].ToString(), out priorityID);
                    //resources
                    int.TryParse(dr["SME"].ToString(), out smeID);
                    int.TryParse(dr["Lead_Tech_Writer"].ToString(), out leadIATWID);
                    int.TryParse(dr["Lead_Resource"].ToString(), out leadResourceID);
                    //int.TryParse(dr["SUBMITTEDBY"].ToString(), out submittedByID);
                    //statuses
                    int.TryParse(dr["TD_STATUS"].ToString(), out td);
                    int.TryParse(dr["CD_STATUS"].ToString(), out cd);
                    int.TryParse(dr["C_STATUS"].ToString(), out c);
                    int.TryParse(dr["IT_STATUS"].ToString(), out it);
                    int.TryParse(dr["CVT_STATUS"].ToString(), out cvt);
                    int.TryParse(dr["A_STATUS"].ToString(), out adopt);
                    int.TryParse(dr["CR_STATUS"].ToString(), out cr);

                    int.TryParse(dr["ARCHIVE"].ToString(), out archive);

                    if (id == 0)
                    {
                        saved   = false;
                        tempMsg = "No Work Request was specified to update.";
                    }
                    else
                    {
                        WorkRequest wr = WorkRequest.WorkRequest_GetObject(id);
                        wr.OP_PRIORITYID   = priorityID;
                        wr.Title           = title;
                        wr.Description     = description;
                        wr.Last_Meeting    = lastMeeting;
                        wr.Next_Meeting    = nextMeeting;
                        wr.Dev_Start       = devStart;
                        wr.CIA_Risk        = string.Empty;
                        wr.CMMI            = string.Empty;
                        wr.SMEID           = smeID;
                        wr.LEAD_IA_TWID    = leadIATWID;
                        wr.LEAD_RESOURCEID = leadResourceID;
                        //wr.SubmittedByID = submittedByID;
                        wr.TD_StatusID  = td;
                        wr.CD_StatusID  = cd;
                        wr.C_StatusID   = c;
                        wr.IT_StatusID  = it;
                        wr.CVT_StatusID = cvt;
                        wr.A_StatusID   = adopt;
                        wr.CR_StatusID  = cr;
                        wr.HasSlides    = hasSlides;
                        wr.WorkStoppage = workStoppage;
                        wr.Archive      = (archive == 1);

                        saved = WorkRequest.WorkRequest_QM_Update(wr, out tempMsg);
                    }
                }

                if (saved)
                {
                    ids += string.Format("{0}{1}", ids.Length > 0 ? "," : "", id.ToString());
                }

                if (tempMsg.Length > 0)
                {
                    errorMsg = string.Format("{0}{1}{2}", errorMsg, errorMsg.Length > 0 ? Environment.NewLine : "", tempMsg);
                }
            }
        }
        catch (Exception ex)
        {
            saved    = false;
            errorMsg = ex.Message;
            LogUtility.LogException(ex);
        }

        result["ids"]   = ids;
        result["saved"] = saved.ToString();
        result["error"] = errorMsg;

        return(JsonConvert.SerializeObject(result, Formatting.None));
    }