基于MVC+EasyUI的Web開發(fā)框架形成之旅--基類控制器CRUD的操作

在上一篇隨筆中搂赋,我對Web開發(fā)框架的總體界面進行了介紹,其中并提到了我的《Web開發(fā)框架》的控制器的設計關系,Web開發(fā)框架沿用了我的《Winform開發(fā)框架》的很多架構設計思路和特點割笙,對Controller進行了封裝。使得控制器能夠獲得很好的繼承關系眯亦,并能以更少的代碼伤溉,更高效的開發(fā)效率,實現(xiàn)Web項目的開發(fā)工作妻率,整個控制器的設計思路如下所示乱顾。


從上圖的設計里面可以看到,我把主要能通過抽象封裝的CRUD方法都放到了BusinessController<B, T>類里面宫静,本文繼續(xù)詳細介紹這個Web框架控制器類的CRUD具體實現(xiàn)糯耍,以便使得大家了解我的整個Web開發(fā)框架的基類控制器的工作原理。

1囊嘉、基類的插入操作

我們知道,一般常規(guī)的插入操作是很普遍的操作革为,那么我們在MVC的Web界面上是如何調用的扭粱,后臺又是如何進行數(shù)據(jù)的處理的呢?
在MVC的View視圖代碼里面震檩,我們添加數(shù)據(jù)的時候琢蛤,javascript腳本代碼是這樣的:

var postData = $("#ffAdd").serializeArray();
$.post("/Information/Insert", postData, function (data) {
    if (data = "true") {
        //添加成功  1.關閉彈出層,2.刷新DataGird
        $.messager.alert("提示", "添加成功");
        $("#DivAdd").dialog("close");
        $("#grid").datagrid("reload");
        $("#ffAdd").form("clear");

        //本頁面的類型為【通知公告】抛虏,固定不變
        $("#Category").val("通知公告");
    }
    else {
        $.messager.alert("提示", "添加失敗博其,請您檢查");
    }
});

其中的serializeArray就把該表單要提交的數(shù)據(jù)序列號到一個字符串里面了,里面的數(shù)據(jù)可能類似A=a&B=b&C=c 這樣的字符串里面了迂猴,通過POST調用控制器Information的Insert方法慕淡,實現(xiàn)數(shù)據(jù)的插入。由于控制器Information是具體業(yè)務類沸毁,因此它繼承自BusinessController<B, T>峰髓,也就是會調用BusinessController<B, T>控制器的Insert方法。
如字典數(shù)據(jù)添加的界面如下所示息尺。


那么后臺的接收方法如何呢?其實后臺是把數(shù)據(jù)序列化到了一個FormCollection對象的集合里面了,但是共缕,我們還可以使用對象T(實體類)熟呛,讓這些數(shù)據(jù)集合賦值給對應的實體對象屬性,如下就是我的后臺控制器的插入方法,它的參數(shù)是一個實體類T并级,這樣我們直接調用業(yè)務操作類就可以插入了拂檩,代碼很簡單易懂。

/// <summary>
/// 插入指定對象到數(shù)據(jù)庫中
/// </summary>
/// <param name="info">指定的對象</param>
/// <returns>執(zhí)行操作是否成功死遭。</returns>
public virtual ActionResult Insert(T info)
{bool result = false;
    if (info != null)
    {
        result = baseBLL.Insert(info);
    }
    return Content(result);
}

2广恢、基類的更新操作

上面我們看了插入數(shù)據(jù)的操作,可能大家對下面介紹的數(shù)據(jù)更新操作呀潭,可能也已經(jīng)有了一些了解了钉迷,其實它和插入操作的方法很類似的。
更新操作的視圖View中腳本代碼如下所示, 它通過控制器Information的Update方法進行更新數(shù)據(jù)钠署。

var ID = $("#ID1").val();
var postData = $("#ffEdit").serializeArray();
$.post("/Information/Update?ID=" + ID, postData, function (date) {
    if (date == "true") {
        //修改成功糠聪,關閉彈出層,刷新DataGird
        $.messager.alert("提示", "修改成功");
        $("#DivEdit").dialog('close');
        $("#grid").datagrid("reload");
    }
    else {
        $.messager.alert("提示", "修改失敗谐鼎,請您檢查");
    }
});

由于控制器Information是具體業(yè)務類舰蟆,因此它繼承自BusinessController<B, T>,也就是會調用BusinessController<B, T>控制器的Update方法狸棍。
和上面的插入操作一樣身害,后臺是把數(shù)據(jù)序列化到了一個FormCollection對象的集合里面了,我們可以使用類似和插入方法的操作草戈,如下所示塌鸯。

/// <summary>
/// 更新對象屬性到數(shù)據(jù)庫中
/// </summary>
/// <param name="info">指定的對象</param>
/// <param name="id">主鍵ID的值</param>
/// <returns>執(zhí)行成功返回<c>true</c>,否則為<c>false</c>唐片。</returns>
public virtual ActionResult Update(T info, string id)
{
    bool result = baseBLL.Update(info, id);
    return Content(result);
}

但是丙猬,如果使用以上的代碼作為更新數(shù)據(jù)的代碼,那么在編輯界面里费韭,如果只是顯示編輯部分表的數(shù)據(jù)茧球,那么可能導致很多屬性會被初始化為實體類的默認值,顯然這樣不符合我們的要求星持,我們可能只是進行部分更新抢埋,那么我們進行部分更新的控制器方法應該如何設計呢?
前面我們說到督暂,數(shù)據(jù)會被序列號到一個FormCollection對象集合里面羹令,更新方法也一樣,那么我們可以把更新操作的接口定義為如下代碼所示损痰,視圖操作代碼不變化:

/// <summary>
/// 更新對象屬性到數(shù)據(jù)庫中
/// </summary>
/// <param name="info">指定的對象</param>
/// <param name="id">主鍵ID的值</param>
/// <returns>執(zhí)行成功返回<c>true</c>福侈,否則為<c>false</c>。</returns>
public virtual ActionResult Update(string id, FormCollection formValues)

我們可以通過調試的方法卢未,查詢到FormCollection里面的值就是我們更新界面里面的數(shù)據(jù)(注意:可能是實體類的部分數(shù)據(jù))肪凛。但使用了這個方法后堰汉,我們還需要把FormCollection對象里面的數(shù)據(jù)轉換為實體類的信息,我們才好調用BaseBLL里面的接口進行更新數(shù)據(jù)伟墙。但是不同的實體類翘鸭,有不同的屬性,我們如何能夠抽象把他們的屬性都賦值了呢戳葵?
答案是通過反射屬性方式就乓,把FormCollection里面屬性的值賦值給對應實體類屬性的值。下面我們來介紹下具體的代碼實現(xiàn)了拱烁。

/// <summary>
/// 更新對象屬性到數(shù)據(jù)庫中
/// </summary>
/// <param name="info">指定的對象</param>
/// <param name="id">主鍵ID的值</param>
/// <returns>執(zhí)行成功返回<c>true</c>生蚁,否則為<c>false</c>。</returns>
public virtual ActionResult Update(string id, FormCollection formValues)
{

    T obj = baseBLL.FindByID(id);
    if (obj != null)
    {
        //遍歷提交過來的數(shù)據(jù)(可能是實體類的部分屬性更新)
        foreach (string key in formValues.Keys)
        {
            string value = formValues[key];
            System.Reflection.PropertyInfo propertyInfo = obj.GetType().GetProperty(key);
            if (propertyInfo != null)
            {
                try
                {
                    // obj對象有key的屬性戏自,把對應的屬性值賦值給它(從字符串轉換為合適的類型)
                    //如果轉換失敗邦投,會拋出InvalidCastException異常
                    propertyInfo.SetValue(obj, Convert.ChangeType(value, propertyInfo.PropertyType), null);
                }
                catch { }
            }
        }
    }

    bool result = baseBLL.Update(obj, id);
    return Content(result);
}

通過對象propertyInfo的SetValue方法,可以把字符串的值擅笔,轉換為實體類對應屬性類型的值志衣,順利進行賦值。

如果是業(yè)務類需要提交一些HTML的代碼猛们,那么我們需要在具體的業(yè)務類里面念脯,重寫插入、更新方法并設置一下 [ValidateInput(false)] 標識才可以弯淘。

[ValidateInput(false)]
public override ActionResult Insert(InformationInfo info)
{
    info.Editor = CurrentUser.Name;
    info.EditTime = DateTime.Now;

    return base.Insert(info);
}

[ValidateInput(false)]
public override ActionResult Update(string id, FormCollection formValues)
{
    return base.Update(id, formValues);
}

如通知公告的內容編輯界面如下所示和二。


3、基類的獲取對象數(shù)據(jù)方法

我們在很多接口里面耳胎,都要求獲取單一對象的數(shù)據(jù)信息,我在基類接口里面定義了一個FindByID方法惕它,就是從業(yè)務對象里面怕午,根據(jù)主鍵ID信息,獲取一個對象的數(shù)據(jù)淹魄,把他轉換為Json傳遞到View視圖里面使用即可郁惜。

/// <summary>
/// 查詢數(shù)據(jù)庫,檢查是否存在指定ID的對象
/// </summary>
/// <param name="id">對象的ID值</param>
/// <returns>存在則返回指定的對象,否則返回Null</returns>
public virtual ActionResult FindByID(string id)
{
    ActionResult result = Content("");
    T info = baseBLL.FindByID(id);
    if (info != null)
    {
        result = JsonDate(info);
    }

    return result;
}

其中的JsonDate方法是為了避免日期類型的數(shù)值在序列化中出現(xiàn)錯誤格式,包裝的一個方法甲锡,如下所示兆蕉。

/// <summary>
/// 返回處理過的時間的Json字符串
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
public ContentResult JsonDate(object date)
{
    var timeConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" };
    return Content(JsonConvert.SerializeObject(date, Formatting.Indented, timeConverter));
}

在View視圖里面使用控制器方法,綁定數(shù)據(jù)到查看界面里面的代碼如下所示缤沦。

//綁定查看詳細信息的方法
function BindViewInfo() {
    var ID = $("#grid").datagrid('getSelections')[0].ID;            
    //發(fā)送請求
    $.getJSON("/Information/FindByID?r=" + Math.random() + "&id=" + ID, function (info) {
        $("#ID2").val(info.ID);
        $("#Title2").text(info.Title);
        $("#Content2").html(info.Content);
        $("#Attachment_GUID2").text(info.Attachment_GUID);
        $("#Editor2").text(info.Editor);
        $("#EditTime2").text(info.EditTime);

        ShowUpFiles(info.Attachment_GUID, 'divViewAttach');
    });
}

具體效果如下所示:


4虎韵、基類刪除操作方法

在GridView里面,我們提供了刪除數(shù)據(jù)的按鈕缸废,具體視圖里面使用的代碼如下所示包蓝。

//然后確認發(fā)送異步請求的信息到后臺刪除數(shù)據(jù)
$.messager.confirm("刪除確認", "您確認刪除選定的記錄嗎驶社?", function (deleteAction) {
    if (deleteAction) {
        $.get("/Information/DeletebyIds", postData, function (data) {
            if (data == "true") {
                $.messager.alert("提示", "刪除選定的記錄成功");
                $("#grid").datagrid("reload");
            }
            else {
                $.messager.alert("提示", data);
            }
        });
    }
});

后臺控制器的基類刪除方法如下所示。

/// <summary>
/// 刪除多個ID的記錄
/// </summary>
/// <param name="ids">多個id組合测萎,逗號分開(1,2,3,4,5)</param>
/// <returns></returns>
public virtual ActionResult DeleteByIds(string ids)
{bool result = false;
    if (!string.IsNullOrEmpty(ids))
    {
        string[] idArray = ids.Split(new char[] { ',' });
        foreach (string strId in idArray)
        {
            if (!string.IsNullOrEmpty(strId))
            {
                baseBLL.Delete(strId);
            }
        }
        result = true;
    }
    return Content(result);
} 

以上就是基類控制器增刪改查的一些通用方法的封裝亡电,業(yè)務對象控制器類,如果有特殊的需要硅瞧,可以對方法進行重寫即可份乒,非常方便使用,從而減少了很多重復編寫的代碼腕唧,并可以使得頁面的操作統(tǒng)一化或辖,提高生產效率。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末四苇,一起剝皮案震驚了整個濱河市孝凌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌月腋,老刑警劉巖蟀架,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異榆骚,居然都是意外死亡片拍,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門妓肢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捌省,“玉大人,你說我怎么就攤上這事碉钠「倩海” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵喊废,是天一觀的道長祝高。 經(jīng)常有香客問我,道長污筷,這世上最難降的妖魔是什么工闺? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮瓣蛀,結果婚禮上陆蟆,老公的妹妹穿的比我還像新娘。我一直安慰自己惋增,他們只是感情好叠殷,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著诈皿,像睡著了一般溪猿。 火紅的嫁衣襯著肌膚如雪钩杰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天诊县,我揣著相機與錄音讲弄,去河邊找鬼。 笑死依痊,一個胖子當著我的面吹牛避除,可吹牛的內容都是我干的。 我是一名探鬼主播胸嘁,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瓶摆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了性宏?” 一聲冷哼從身側響起群井,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎毫胜,沒想到半個月后书斜,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡酵使,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年荐吉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片口渔。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡样屠,死狀恐怖,靈堂內的尸體忽然破棺而出缺脉,到底是詐尸還是另有隱情痪欲,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布攻礼,位于F島的核電站业踢,受9級特大地震影響,放射性物質發(fā)生泄漏秘蛔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一傍衡、第九天 我趴在偏房一處隱蔽的房頂上張望深员。 院中可真熱鬧,春花似錦蛙埂、人聲如沸倦畅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叠赐。三九已至欲账,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間芭概,已是汗流浹背赛不。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留罢洲,地道東北人踢故。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像惹苗,于是被迫代替她去往敵國和親殿较。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內容