ASP.NET MVC之持久化TempData及擴展方法(十三)


前言

之前在開始該系列之前我們就講述了在MVC中從控制器到視圖傳遞數據的四種方式,但是還是存在一點問題,本節就這個問題進行講述同時進行一些練習來看看MVC中的擴展方法。

話題

廢話不必多說,我們直接進入主題,關於TempData的基本用法就不需要再進行講述,其生命周期確實很短,但是對於其用法也就存在一定可能性,當我們需要從一個頁面到另外一個頁面進行數據傳遞時,此時就需要用到該對象。該對象數據進行第一次加載后則其生命周期結束,但是我們如何做到持久化該對象中的數據呢?請往下看。

持久化TempData

我們首先來看一個例子。

    public class TempDataController : Controller
    {
        public ActionResult Index()
        {
            TempData["cnblogs"] = "xpy0928";
            return View();
        }

        public ActionResult GetTemData()
        {
            var blogName = TempData["cnblogs"].ToString();
            return View();
        }

    }

當第一次訪問 GetTemData 時,會正確顯示 blogName = "xpy0928" ,當刷新該頁面時則出現【未將該對象實例化到對象的實例】。

那么問題來了,我們如何持久化該TempData中的數據即刷新該頁面時使該對象的數據不為null。 

原來在MVC中是利用 Keep 方法來實現該對象中的數據持久化。我們來看看。

    public class TempDataController : Controller
    {
        public ActionResult Index()
        {
            TempData["cnblogs"] = "xpy0928";
            TempData.Keep(); return View();
        }

        public ActionResult GetTemData()
        {
            var blogName = TempData["cnblogs"].ToString();
            TempData.Keep("cnblogs");
            return View();
        }

    }

此時當我們即使多次刷新頁面GetTemData視圖時則該對象的鍵cnblogs對應的值都一直存在。 

RedirectToRouteResult和RedirectResult

下面我們再來看一例。

        public ActionResult Index()
        {
            TempData["cnblogs"] = "xpy0928";
            return new RedirectToRouteResult(new
                        RouteValueDictionary(new { controller = "TempData", action = "GetTemData" }));
        }

        public ActionResult GetTemData()
        {
            var blogName = TempData["cnblogs"].ToString();
            TempData.Keep("cnblogs");
            return View();
        }

在上述中我們在Index方法中未直接調用 TempData.Keep() ,此時直接重定向到GetTemData方法,當再次刷新時,該對象中的值仍存在。也就是說RedirectToRouteResult默認是一直調用TempData.Keep方法使其對象的值一直存在(對於RedirectResult同理)。

void Keep()

在當前Action方法中調用Keep方法則保證在當前請求中TempData對象中所存儲的鍵都不會被移除。

void Keep(string key)

在當前Action方法中調用Keep方法保證在當前請求中TempData對象中的某一特定項不會被移除。

總結

(1)當利用TempData對象存儲值而未調用TempData.Keep方法時,此時只要該對象被已讀,然后該對象中的所有項將被標記為刪除狀態。

(2)若調用TempData.Keep(string key)方法,此時不會進行標記。

(3)RedirectToRouteResult和RedirectResult總是會調用TempData.Keep()方法,保證該對象中的所有項不會被移除。

 MVC擴展方法

這一小節的寫出是通過對出現的問題進行解決而想到,下面我將一步一步來進行演示。

在實際應用中我們會遇到利用Tab來切換得到不同的視圖。下面我們用Bootstrap來實現,如下:

<ul id="nav" class="nav nav-tabs">
    <li class="active"><a href="/Professional/Rota">值班表</a></li>
    <li><a href="/Professional/OverValue">超有限值</a></li>
    <li><a href="/Professional/NoOverValue">無超有限值</a></li>
    <li><a href="/Professional/DifferenceWeight">差值加權</a></li>
    <li><a href="/Professional/Difference">差值</a></li>
    <li><a href="/Professional/ClassTotal">班總和</a></li>
    <li><a href="/Professional/ClassAverage">班平均</a></li>
</ul>

將得到如下效果:

那么問題來了,有七個tab,那么是不是應該在每個頁面都得定義如上的一個Ul,而唯一不同的只是切換不同li,則該li的樣式為active呢?

剛開始我也是這樣做的,后來越想越不對勁,每個頁面都這樣定義一下,而只是激活點擊的li為active。此時想到的是將上述Ul定義為一個母版頁,而想辦法對其點擊的class為active即可,於是出現了如下:

@{
    ViewBag.Title = "_TabLayout";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<ul id="nav" class="nav nav-tabs">
    <li><a href="/Professional/Rota">值班表</a></li>
    <li><a href="/Professional/OverValue">超有限值</a></li>
    <li><a href="/Professional/NoOverValue">無超有限值</a></li>
    <li><a href="/Professional/DifferenceWeight">差值加權</a></li>
    <li><a href="/Professional/Difference">差值</a></li>
    <li><a href="/Professional/ClassTotal">班總和</a></li>
    <li><a href="/Professional/ClassAverage">班平均</a></li>
</ul>
@RenderBody()
<script type="text/javascript">
    $(function () {
        $("#nav li").eq(0).addClass("active");
    });
</script>

其他tab都用上述js來添加樣式active。(當然可直接在模板中控制點擊的li再添加樣式比上述更簡潔,就不再演示)。

下面我們不用Bootstrap,自定義並用MVC擴展方法來實現切換tab(利用js不再敘述)。

(1)母版頁變成如下 

@{
    ViewBag.Title = "_TabLayout";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@using PowerAssessmentSystem.MvcExtend;

<link href="~/Content/tab.css" rel="stylesheet" type="text/css" />
<div class="menu-tabs">
    <ul>
        <li>@Html.ActiveLink("值班表", "Rota", "Professional")</li>
        <li>@Html.ActiveLink("超有限值", "OverValue", "Professional")</li>
        <li>@Html.ActiveLink("無超有限值", "NoOverValue", "Professional")</li>
        <li>@Html.ActiveLink("差值加權", "DifferenceWeight", "Professional")</li>
        <li>@Html.ActiveLink("差值", "Difference", "Professional")</li>
        <li>@Html.ActiveLink("班總和", "ClassTotal", "Professional")</li>
        <li>@Html.ActiveLink("班平均", "ClassAverage", "Professional")</li>
      
    </ul>
</div>

@RenderBody()

(2)@Html.ActiveLink擴展方法實現點擊Active樣式

    public static class ActiveHelper
    {
        public static MvcHtmlString ActiveLink(this HtmlHelper helper, string linkText, string actionName, string controllerName)
        {
            var routevalueDic = new RouteValueDictionary();
            var acName = helper.ViewContext.RouteData.Values["action"].ToString();
            var ctlName = helper.ViewContext.RouteData.Values["controller"].ToString();
            if (acName.Equals(actionName, StringComparison.OrdinalIgnoreCase))
            {
                if (ctlName.Equals(controllerName, StringComparison.OrdinalIgnoreCase))
                {
                    routevalueDic.Add("class", "active");
                }
            }
 
            return helper.ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(), routevalueDic);
        }
    }

(3)相關樣式

a:hover {
    text-decoration: none;
    color: #f01400;
}

.menu-tabs {
    border-bottom: 1px solid #D1D6DA;
}

    .menu-tabs ul {
        height: 45px;
        line-height: 45px;
    }

    .menu-tabs li {
        list-style-type: none;
        float: left;
        height: 100%;
        text-align: center;
        width: 13.63636364%;
    }

    .menu-tabs a {
        display: block;
        font-size: 16px;
    }

.active {
    color: #f01400;
    font-weight: bold;
    border-bottom: 2px solid #f01400;
    height: 55px;
}

我們再來看看最終的演示效果:

總結

本節我們講解了TempData的持久化以及MVC中擴展方法,本節結束。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM