C# .NETCORE3.1 系列教程(三) 控制器中控制頁面彈出提示框功能實現(ViewComponent實現)


實現效果

視圖頁展示

 

 

Controller的Action調用方法

 

 

了解ViewComponent
ViewComponent,簡稱視圖組件,你可以在任何可重復使用的渲染邏輯的部分視圖中用視圖組件來替換,那么就能夠實現在一個View中嵌入一些相同或類似的內容(相當於能在他的父視圖的對應位置插入相應的Html代碼)。當然,.net也有提供一個partial views可以實現,或者使用ChildConrtoller,但是,partial views並不能另外寫一個控制器進行數據的特殊處理,而ChildConrtoller的開銷則比較大,效率更低,因為需要走完整個Controller的過程。ViewComponent提供了一個獨立的控制器,可以讓你在服務端中對數據進行查詢、計算和控制。

因為網上沒有比較直觀的定義,所以這個定義是我的個人理解。

比如一個網頁,每一頁的頂部和導航欄可能是相同或類似的,每個頁面去寫比較麻煩,而且如果需要修改,你需要在非常多頁里面進行修改,這樣做的方式並不友好,所以,此時你就考慮寫一個視圖組件,修改時只要修改這個組件,其他頁在相應位置嵌入這個組件即可。

我們的這個彈窗也可以看作一個組件,在每個頁面底部都嵌入這個組件,當發現傳入的msg有內容時,就可以彈窗一個彈窗(如用js的alert函數,或者如果你有引入其他前端框架你可以寫成其他的方式),否則這個組件不會做任何操作。

創建ViewComponent控制器
我們需要先在項目中創建一個名為“ViewComponents”的目錄,按照約定,所有自定義視圖組件的控制器類默認情況下都存放在這個目錄下。

我們在這個目錄下創建一個名為“MessageBox”的視圖組件控制器,我們創建一個類,名為MessageBoxViewComponent(按約定,視圖組件的控制器類都組件名稱+“ViewComponent”命名)

MessageBoxViewComponent 繼承Microsoft.AspNetCore.Mvc.ViewComponent類 ,代碼如下:

先添加引用

using Microsoft.AspNetCore.Mvc;

然后繼承,如果需要依賴注入請按上一章節的方式注冊服務和注入

     public class MessageBoxViewComponent : ViewComponent
    {
        //private readonly LogHandler _logHandler;
    
            //public MessageBoxViewComponent(LogHandler logHandler)//依賴注入日志操作服務實例,需要在Startup中注冊
            //{
            //    this._logHandler = logHandler;
            //}
    }

接下來需要在控制器類中添加一個InvokeAsync函數,返回類型為IViewComponentResult(Task),該函數異步執行,可以自定義接收參數,我們可以在視圖中為他傳參

        public async Task<IViewComponentResult> InvokeAsync(MessageBoxVO options)//傳入參數為MessageBoxVO類型的options(彈窗信息選項)
        {
            if (options == null || (string.IsNullOrEmpty(options.Msg) && string.IsNullOrEmpty(options.RedrectUrl)))
                return Content("");//如果彈窗信息選項為空或內容和跳轉URL均為空,證明不跳轉,該組件直接輸出空內容即可
            //如果需要記錄日志,可以在此進行操作如:await  _logHandler.CustomMessage(model);
            return View(options);//否則返回視圖(一段彈窗控制的JS)
        }

MessageBoxVO類是彈窗組件的配置選項類,代碼如下:

public class MessageBoxVO
    {
        public string Msg { get; set; }

        public string RedrectUrl { get; set; }


        public string Title { get; set; }
    }

創建ViewComponent視圖
前文已經說了,組件的視圖主要是一段控制彈窗的JS。按照約定,我們可以在項目視圖目錄(Views目錄)下,創建一個名為“Components”的目錄存放視圖組件的視圖,也可以在Views/Shared下(跟 _Layout一個目錄,我習慣放在這個目錄下)創建一個名為“Components”的目錄存放視圖組件的視圖。

Components目錄中需要按照組件的名稱建立文件夾,目錄結構如下:

 

我們的彈窗組件名稱為“MessageBox”,所以需要在Components目錄下再建立一個“MessageBox”目錄。

我們的控制器中沒有指定返回哪個視圖,因此我們可以創建一個默認視圖“Default.cshtml”。

該視圖綁定的Model類型為MessageBoxVO

具體代碼如下

@model WebApplication1.Models.MessageBoxVO
    <script>
        //這是一個JS自執行函數,在該函數創建完成后將會自動調用,因為頁面的JS是按照順序執行的,所以將它放在頁面Body的最底部,將會在頁面渲染完成自動執行
        !function (msg, redrectUrl) { //函數接收msg和redrectUrl兩個參數,第一個為提示內容,第二個為跳轉地址
            if (msg && msg.toString().length > 0)//如果存在msg則彈出
            {
                alert(msg);
            }
            if (redrectUrl && redrectUrl.toString().length > 0)//如果redrectUrl有內容則在彈窗被關閉(點確認)后會繼續執行頁面跳轉
            {
                parent.location.href = redrectUrl;
            }
        }
            (
                //在這里給自執行函數傳參
                @Html.Raw((Model == null ? "null" : "'"+Model.Msg+"'")),
                @Html.Raw(( Model == null ? "null" : "'" +Model.RedrectUrl+"'"))
            );
    </script>

引用組件

視圖組件的引入方式是視圖需要引入的地方使用Component.InvokeAsync方法引入,最終這個地方將會被組件的Html替換
Component.InvokeAsync方法的定義如下:

Task<IHtmlContent> InvokeAsync(string name, object arguments);//Component.InvokeAsync方法有兩個參數,第一個參數為組件名稱,即“MessageBox”,第二個參數是傳入參數,是一個對象,可以使用new{…… }的方式創建一個匿名對象

我們在可以在視圖模板中統一引入組件,這樣每個頁面都會在最底部自動引入MessageBox組件

打開_Layout.cshtml,在Body的最后用Component.InvokeAsync方法引入組件,

調用代碼:

@await Component.InvokeAsync("MessageBox", new { model = ViewBag.SystemMessageBoxInfo == null ? null : ViewBag.SystemMessageBoxInfo as WebApplication1.Models.MessageBoxVO })

我們看其中這段代碼

ViewBag.SystemMessageBoxInfo as WebApplication1.Models.MessageBoxVO

父頁面的控制器將參數傳入給組件我們采用的是ViewBag,如果需要彈出窗口,就在ViewBag創建一個名為“SystemMessageBoxInfo”的鍵,並將彈窗配置對象賦值給他即可

_Layout.cshtml頁全部代碼:

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <environment include="Development">
        <link rel="stylesheet" asp-href-include="css/*" asp-href-exclude="css/all.min.css" />
    </environment>
    <environment exclude="Development">
        <link rel="stylesheet"  asp-href-include="all.min.css" />
    </environment>
</head>
<body>
    <div>
        <img src="/img/logo.jpg" asp-append-verison="true" alt="Jxmaker.com" style="width:20%" />
    </div>
    <div>
        @RenderBody()
    </div>
    <!--彈窗組件引入-->
    @await Component.InvokeAsync("MessageBox", new { options= ViewBag.SystemMessageBoxInfo == null ? null : ViewBag.SystemMessageBoxInfo as WebApplication1.Models.MessageBoxVO })
    <!--彈窗組件引入結束-->
</body>
</html>

在Controller中控制頁面彈出一個彈窗
在上一章中,我們創建控制器時有介紹控制器都是繼承Microsoft.AspNetCore.Mvc.Controller類,我們可以寫一個自定義的控制器基類,繼承Microsoft.AspNetCore.Mvc.Controller類,並定義一個函數,取名為“MessageBoxView”。這個函數最終返回一個實現IActionResult的實例,並實現彈窗傳值。

直接看控制器基類代碼:

namespace WebApplication1.Code
{
    public class WebBaseController: Controller //Web視圖控制器基類繼承Microsoft.AspNetCore.Mvc.Controller
    {
        /// <summary>
        /// 返回對應視圖並進行彈窗
        /// </summary>
        /// <param name="msg">提示信息,為null或空字符串則不彈窗</param>
        /// <param name="redrectUrl">跳轉地址,為null或空字符串則不跳轉</param>
        /// <returns></returns>
        protected IActionResult MessageBoxView(string msg, string redrectUrl=null)
        {
            ViewBag.SystemMessageBoxInfo = new MessageBoxVO()//通過ViewBag將彈窗配置信息傳值給視圖,視圖再傳值給MessageBox組件
            {
                Msg = msg,
                RedrectUrl = redrectUrl
            };
            return base.View();//返回對應視圖
        }

        /// <summary>
        /// 返回對應視圖並進行彈窗
        /// </summary>
        /// <typeparam name="T">視圖綁定Model類型</typeparam>
        /// <param name="msg">提示信息,為null或空字符串則不彈窗</param>
        /// <param name="redrectUrl">跳轉地址,為null或空字符串則不跳轉</param>
        /// <param name="model">傳入視圖Model,為null則自動通過new創建一個Model實例傳入給視圖</param>
        /// <returns></returns>
        protected IActionResult MessageBoxView<T>(string msg, string redrectUrl=null,T model=default) where T:new ()
        {
            if (model == null)//如果傳入視圖的Model為Null則通過new創建一個Model實例傳入給視圖
                model = new T();
            ViewBag.SystemMessageBoxInfo = new MessageBoxVO()//通過ViewBag將彈窗配置信息傳值給視圖,視圖再傳值給MessageBox組件
            {
                Msg = msg,
                RedrectUrl = redrectUrl
            };
            return base.View(model);//返回對應視圖
        }

    }
}

例1

當瀏覽職員列表頁未指定部門時,提示”您沒有權限查看全部職員,請按部門查找“,並跳轉到部門列表頁

我們需要彈窗的控制器類(EmployeeController)需要先繼承自定義的基類(WebBaseController)

    public class EmployeeController:WebBaseController
    {
    }

修改控制器中Index的Action,判斷是否有deptId傳值(並判斷是否合規),如果沒有(或不合規)就提示

 public async Task<IActionResult> Index(int? deptId,string name,bool? isFired)
        {
            //判斷是否指定部門或是否指定的部門id不合規,如果是就彈窗提示並跳轉到部門列表
            if(!deptId.HasValue||deptId.Value<1)
                return MessageBoxView<List<EmployeeInfo>>("您沒有權限查看全部職員,請按部門查找","../Dept/Index");
            ViewBag.DeptId = deptId;
            ViewBag.Title = (deptId.HasValue? (await _deptService.GetSingle(deptId.Value)).Name :"全部")+"成員列表";
            var list = await _employeeService.GetList(deptId, name, isFired);
            return View(list);
        }

例2

部門添加成功后需要彈窗提示添加成功,點確定后跳轉到部門列表頁

我們需要彈窗的控制器類需要先繼承自定義的基類

public class DeptController:WebBaseController
{
}

修改該控制器下名為“Add"的Action

 public async Task<IActionResult> Add(DeptInfo model)
        {
            if (!ModelState.IsValid)
                return null;
            await _deptService.Add(model);
            //return RedirectToAction(nameof(Index));   //原來的寫法
            return MessageBoxView<DeptInfo>(msg:"添加成功",model:model,redrectUrl:"Index");
        }

此時就能夠實現在控制器中控制頁面彈出提示框並在點擊確定后跳轉。

總結與思考
如此我們就完成了控制器中控制頁面彈出提示框功能實現。

思考:

現在這種方式用戶可以看到頁面的內容,才會展示提示框,如果我不想讓用戶看到頁面內容,直接彈出提示和跳轉,要怎么做?

思考答案:

修改_Layout.cshtml,將組價引入移到<head>標簽的結尾,因為html頁面渲染是由上到下的,此時我們使用了自執行函數,渲染到這一步就會跳轉,body中的頁面內容還沒渲染

教程Demo下載地址:
https://download.csdn.net/download/zinechina/12634702


————————————————
版權聲明:本文為CSDN博主「紅鮮森」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zinechina/article/details/107428180

 


免責聲明!

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



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