> For the complete documentation index, see [llms.txt](https://kerryhuangs-organization.gitbook.io/kerry-de-bi-ji-ben/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kerryhuangs-organization.gitbook.io/kerry-de-bi-ji-ben/asp.net-core-jiao-yu-xun-lian-wen-jian/asp.net-core-hou-tai-cha-xun-ye-mian-jiao-xue.md).

# ASP.NET Core 後台查詢頁面教學

�����}�o�\`�����@�إ\��O�b��x�s�W���@��ơA�M��b�e�x��ܸ�ơA�����������i�γ̷s�����\��A�����оǱN�|�ЧA�p��إ߫�x���i���@�ɭ��A�æb�e�x��ܸ�ơC

���оǽd�ҷ|�إ� ASP.NET Core MVC �s�M�סA�s�W�@�ӫ�x���i�޲z�����A�z�L�d����ܸ�Ʈw�������i��ơC

�d�ߥ�����Ƨe�{�O²�檺�ʧ@�A�ӧڷ|�\[�W�����d�߬۹�O���������ʧ@�A�ڷ|�ܽd�@�ӧڱ\`�Ϊ�������k���U��ѦҡC

���d�Ҩϥ� ASP.NET Core MVC �����O .NET6�A�e�ݨϥ� Vue3 �ج\[�A��ݸ�Ʈw�ϥ� SQL Server 2019�A�ϥ� Dapper �M��s�u�A�好���d�ҥi�H�U���C

**�ؿ�**

[1 �إ߱M��](#step1)\
\[2 �]�p�d�߭���]\(#step2)\
[3 ��Ʈw�y�k](#step3)\
\[4 �M�װ�¦�]�w]\(#step4)\
\[4.1 �[�J Vue3 �M��](#step5)\
\[4.2 �[�J jQuery BlockUI Plugin �M��](#step6)\
\[4.3 ���� Json �^�ǹw�]�p�g�]�w]\(#step7)\
[5 �d�ߤ��i](#step8)\
\[5.1 View ���[ Vue3 �y�k](#step9)\
[5.2 Controller �y�k](#step10)\
[5.3 Ū�� appsettings.json](#step11)\
[5.4 �w�� Dapper](#step12)\
[5.5 �إ� ViewModel](#step13)\
\[6 �W�[�����d�ߥ\��](#step14)\
[6.1 �s�W VuePagination.js ����](#step15)\
[6.2 �ޥ� VuePagination.js ����](#step16)\
[6.3 ���U VuePagination.js ����](#step17)\
[6.4 �ϥΤ�������](#step18)\
[6.5 View �d�ߥ\��վ�](#step19)\
\[6.6 grid ����W�[�����ݩ�](#step20)\
[6.7 Controller �d�ߥ\��վ�](#step21)\
[6.8 ViewModel �վ�](#step22)\
[6.9 �d�ҤU��](#step23)

### �إ߱M��

�}�� Visual Studio 2022�A�إ߷s�M�׬��uASP.NET Core Web ���ε{�� (Model-View-Controller)�v�C

![img1](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-1.png)

��J�M�צW�١B���|�C

![img2](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-2.png)

�\[�c��ܡu.NET 6.0�v�����A���U�u�إߡv�N�|�إߦ��M�סC

![img3](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-3.png)

### �]�p�d�߭���

�o�̧ڭ̷s�W�@�� Controller �M���B�z��x�����i���@�C �b Controllers ���k��s�W�@�ӡu����v�C

![img4](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-4.png)

��ܡuMVC ��� �V �ťաv, ���W���uAdmAnnoController�v�C

�b \Controllers\AdmAnnoController.cs �ɮת� Index() ���k���u�s�W�˵��v�A�i�H�s�W���� View �����C

![img5](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-5.png)

��ܡuRazor �˵��v�A�W�ٺ����w�]�uIndex�v�A�Ŀ�u�ϥΪ����t�m���v�A���u�s�W�v�C

![img5-1](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-5-1.png)

�e���]�p�ڭ̴N�q [Bootstrap](https://getbootstrap.com/docs/5.0/getting-started/introduction/) �ƻs�@�ǾA�X�d����ܪ��d�Ҩ� View �̭��C �ڥΨ쪺�˦��� [Card](https://getbootstrap.com/docs/5.0/components/card/), [Form](https://getbootstrap.com/docs/5.0/forms/overview/), [Table](https://getbootstrap.com/docs/5.0/content/tables/), [Button](https://getbootstrap.com/docs/5.0/components/buttons/)

�ڳ]�p�F�d�ߵe���A�����ϥΥH�U�y�k���N \Views\AdmAnno\Index.cshtml �즳���y�k�C

```XHTML
<div id="QueryPanel" class="card">
    <div class="card-header">
        ���i���@
    </div>
    <div class="card-body">
        <div class="row">
            <div class="col-auto">
                <label for="AnnoSubject" class="col-form-label">���i�D�D</label>
            </div>
            <div class="col-auto">
                <input type="text" id="AnnoSubject" class="form-control">
            </div>
            <div class="col-auto">
                <label for="AnnoStatus" class="col-form-label">���i���A</label>
            </div>
            <div class="col-auto">
                <select class="form-select" id="AnnoStatus">
                    <option value="1">���</option>
                    <option value="0">����</option>
                </select>
            </div>
        </div>
    </div>
    <div class="card-header">
        <button type="button" class="btn btn-primary">�d��</button>
    </div>
	<div class="card-body">
		<table class="table">
			<thead>
				<tr>
					<th>���i���</th>
					<th>���i�D�D</th>
					<th>���i���e</th>
					<th>���i���A</th>
				</tr>
			</thead>
			<tbody>
			</tbody>
		</table>
	</div>
</div>
```

�NProgram.cs�ɮ׭˼ƲĤG�檺`pattern: "{controller=Home}/{action=Index}/{id?}");`�אּ`pattern: "{controller=AdmAnno}/{action=Index}/{id?}");`�C

�� F5 ���������N�|�ݨ�H�U���e���C

![img6](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-6.png)

����o�̥D�n�O���]�p�ڭ̪��e���A���U�ӴN�n�]�p��Ʈw�M��}�l�g�{���X�F�C

### ��Ʈw�y�k

�ڭ̷|�ϥ� SQL Server �ӷ��@��ƨӷ��A�ڤw�g�s�W�n ��Teach�� ����Ʈw�F�A���ۥH�U�y�k�s�W���i Table�C

```Transact-SQL
CREATE TABLE [dbo].[Announcement] (
[Pkey] int IDENTITY(1, 1) NOT NULL,
[AnnoDate] date NOT NULL,
[AnnoSubject] nvarchar(50) NOT NULL,
[AnnoContent] nvarchar(1000) NOT NULL,
[AnnoStatus] smallint NOT NULL,
PRIMARY KEY CLUSTERED ([Pkey] ASC)
 ON [PRIMARY]
)
```

���F Table ����A�o�̧ڴN�����s�W 16 �����ո�ơA�]���ڭ̲Ĥ@�ӥ\��O�d�ߡA���F��Ƥ\~��ݥX���G�C

```Transact-SQL
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-01 00:00:00',N'Subject1',N'Content1',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-02 00:00:00',N'Subject2',N'Content2',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-03 00:00:00',N'Subject3',N'Content3',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-04 00:00:00',N'Subject4',N'Content4',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-05 00:00:00',N'Subject5',N'Content5',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-06 00:00:00',N'Subject6',N'Content6',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-07 00:00:00',N'Subject7',N'Content7',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-08 00:00:00',N'Subject8',N'Content8',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-09 00:00:00',N'Subject9',N'Content9',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-10 00:00:00',N'Subject10',N'Content10',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-11 00:00:00',N'Subject11',N'Content11',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-12 00:00:00',N'Subject12',N'Content12',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-13 00:00:00',N'Subject13',N'Content13',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-14 00:00:00',N'Subject14',N'Content14',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-15 00:00:00',N'Subject15',N'Content15',1)
insert into [dbo].[Announcement]([AnnoDate],[AnnoSubject],[AnnoContent],[AnnoStatus]) values ('2022-02-16 00:00:00',N'Subject16',N'Content16',1)
```

### �M�װ�¦�]�w

�o�̷|���w�� ASP.NET Core MVC �M�׼W�\[�@�ǰ�¦�]�w�A�H��K����}�o�C

#### �\[�J Vue3 �M��

Vue3 �O�e�ݱ�����쪺�ج\[���O�w�A���} \Views\Shared\_Layout.cshtml �ɮסA�b�U�� JavaScript �ޥμW�\[ Vue3 ���O�w�y�k�A���Ǫ��n�D�n��b jQuery ����\~��C

`<script src="https://unpkg.com/vue@3"></script>`

![img7](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-7.png)

���b Layout �\[�W Vue3 �ޥΫ�A�ڭ̴N�i�H�b�Ҧ��������ϥ� Vue3 �y�k�F�A���ޥλy�k�ӷ��i�Ѧҩx����C

#### �\[�J jQuery BlockUI Plugin �M��

[jQuery BlockUI](https://jquery.malsup.com/block/) �O���e�ݦV��ݩI�s�ɡA�Ȯ���w�e�ݵe���A�H����G���I�������D�C �b���\[�J Vue3 �M�󪺤U��A�\[�J�ޥλy�k�C

`<script src="https://malsup.github.io/jquery.blockUI.js"></script>`

#### ���� Json �^�ǹw�]�p�g�]�w

�b .NET Framework �ϥ� Json �^�ǮɡA�e�ݦ��쪺 Json ����j�p�g�]�w�P ViewModel �ۦP�A�Ӧb .NET Core �ɫh�w�]�}�Y���p�g (�m�p���R�W)�A�o�̧ڳ��|�վ㦨�P ViewModel �ۦP�C

�b Program.cs �\[�J�H�U�y�k�G

```C#
// ���� Json �^�Ǥj�p�g�P ViewModel �ۦP
builder.Services.AddControllers().AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.PropertyNamingPolicy = null;
    });
```

![img7-1](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-7-1.png)

### �d�ߤ��i

�o�̷|�}�l�g�{���X�A�b�]�p�e���W�� 2 �Ӭd�����A1 �Ӭd�߫��s�A�����U�d�߶s��A�a�J�d�߱���A�q��Ʈw��Ū����Ƨe�{�C

#### View ���\[ Vue3 �y�k

���ڭ̦b Index.cshtml �ϥ� Bootstrap �]�p�n�F�e���A���ۭn�\[�W Vue3 ���d�߰ʰ\_�ӡC �N�H�U���y�k�����л\�� \Views\AdmAnno\Index.cshtml �̭��C

```JavaScript
<div id="app">
    <div id="QueryPanel" class="card">
        <div class="card-header">
            ���i���@
        </div>
        <div class="card-body">
            <div class="row">
                <div class="col-auto">
                    <label for="queryFormAnnoSubject" class="col-form-label">���i�D�D</label>
                </div>
                <div class="col-auto">
                    <input type="text" id="queryFormAnnoSubject" class="form-control" v-model="queryForm.AnnoSubject">
                </div>
                <div class="col-auto">
                    <label for="queryFormAnnoStatus" class="col-form-label">���i���A</label>
                </div>
                <div class="col-auto">
                    <select class="form-select" id="queryFormAnnoStatus" v-model="queryForm.AnnoStatus">
                        <option value="1">���</option>
                        <option value="0">����</option>
                    </select>
                </div>
            </div>
        </div>
        <div class="card-header">
            <button type="button" class="btn btn-primary" v-on:click="Query()">�d��</button>
        </div>
		<div class="card-body">
			<table class="table">
				<thead>
					<tr>
						<th>���i���</th>
						<th>���i�D�D</th>
						<th>���i���e</th>
						<th>���i���A</th>
					</tr>
				</thead>
				<tbody>
					<tr v-for="(item, index) in grid.datas">
						<td>{{item.AnnoDate}}</td>
						<td>{{item.AnnoSubject}}</td>
						<td>{{item.AnnoContent}}</td>
						<td>{{item.AnnoStatusName}}</td>
					</tr>
				</tbody>
			</table>
		</div>
    </div>
</div>
@section scripts {
<script>
    const app = Vue.createApp({
    data() {
        return {
            queryForm:{
                AnnoSubject: ''
                , AnnoStatus: '1'
            }
            , grid:{
                datas:[]
            }
        }
    }
    , methods: {
        Query() {
            var self = this;
 
            // �զX������
            var postData = {};
            postData['AnnoSubject'] = self.queryForm.AnnoSubject;
            postData['AnnoStatus'] = self.queryForm.AnnoStatus;
			
            $.blockUI();
            // �ϥ� jQuery Ajax �ǰe�ܫ��
            $.ajax({
                url:'@Url.Content("~/AdmAnno/Query")',
                method:'POST',
                dataType:'json',
                data: { inModel: postData },
                success: function (datas) {
					$.unblockUI();
                    if (datas.ErrMsg) {
                        alert(datas.ErrMsg);
                        return;
                    }
                    // �j�w�C��
                    self.grid.datas = datas.Grid;
                },
                error: function (err) {
                    $.unblockUI();
                    alert(err.status + " " + err.statusText + '\n' + err.responseText);
                }
            });
 
        }
      }
    });
	const vm = app.mount('#app');
</script>
}
```

#### Controller �y�k

�b View �d�߫�|�I�s \~/AdmAnno/Query�A�b \Controllers\AdmAnnoController.cs �\[�J�H�U Action�C

```C#
/// <summary>
/// �d�ߤ��i
/// </summary>
/// <param name="inModel"></param>
/// <returns></returns>
public IActionResult Query(QueryIn inModel)
{
	QueryOut outModel = new QueryOut();
	outModel.Grid = new List<AnnoModel>();
 
	// ��Ʈw�s�u�r��
	string connStr = _configuration.GetConnectionString("SqlServer");
	using (var cn = new SqlConnection(connStr))
	{
		// �D�n�d�� SQL
		string sql = @"SELECT Pkey, CONVERT(varchar(12) , AnnoDate, 111 ) as AnnoDate, AnnoSubject, AnnoContent, AnnoStatus, Case AnnoStatus when '1' then '���' when '0' then '����' end As AnnoStatusName
						FROM Announcement 
						WHERE 1=1 ";
 
		if (!string.IsNullOrEmpty(inModel.AnnoSubject))
		{
			sql += " AND AnnoSubject LIKE @AnnoSubject ";
		}
		if (!string.IsNullOrEmpty(inModel.AnnoStatus))
		{
			sql += " AND AnnoStatus = @AnnoStatus ";
		}
		sql += " ORDER BY AnnoDate desc, AnnoStatus ";
		
		object param = new
		{
			AnnoSubject = "%" + inModel.AnnoSubject + "%",
			AnnoStatus = inModel.AnnoStatus
		};
		
		// �ϥ� Dapper �d��
		var list = cn.Query<AnnoModel>(sql, param);
		
		// ��X����
		foreach (var item in list)
		{
			outModel.Grid.Add(item);
		}
	}
	return Json(outModel);
}
```

#### Ū�� appsettings.json

�ڱN��Ʈw�s�u��b appsettings.json �̭��A���} appsettings.json ��A�\[�J�H�U�s�u�r��C

```Jason
"ConnectionStrings": {
	"SqlServer": "Data Source=127.0.0.1;Initial Catalog=Teach;Persist Security Info=false;User ID=test;Password=test;"
}
```

![img8](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-8.png)

�b .NET 6 �n���o appsettings.json ���]�w�ӷ��A�n�b Controller �W�\[�غc�lŪ�� Configuration�C

```C#
private readonly IConfiguration _configuration;
 
public AdmAnnoController(IConfiguration configuration)
{
	_configuration = configuration;
}
```

#### �w�� Dapper

�ڸ�Ʈw���ʪ���ϥηL�� ORM �M�� Dapper�A�ݭn�w�� Dapper �\~��ϥΡC �}�ҡu�M�� > �޲z NuGet �M��v�C

![img9](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-9.png)

�j�M�uDapper�v�A�w�˦��M��C

![img10](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-10.png)

#### �إ� ViewModel

ViewModel �O�Ψөw�q Controller �P View ���������w�q�A�ڭ̭��إߤF�s Controller�A�ҥH�o���ӫإߥ������� ViewModel�C �b�uModel ���k�� > �\[�J > ���O�v�C

![img11](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-11.png)

�M��R�W�� ��AdmAnnoViewModel���C

![img12](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-12.png)

�M��b AdmAnnoViewModel ���O�̭��A�\[�J�b Controller �Ψ쪺 ViewModel�C

```C#
public class QueryIn
{
	public string AnnoSubject { get; set; }
	public string AnnoStatus { get; set; }
}
 
public class QueryOut
{
	public List<AnnoModel> Grid { get; set; }
}
 
public class AnnoModel
{
	public string Pkey { get; set; }
	public string AnnoDate { get; set; }
	public string AnnoSubject { get; set; }
	public string AnnoContent { get; set; }
	public string AnnoStatus { get; set; }
	public string AnnoStatusName { get; set; }
}
```

![img12-1](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-12-1.png)

������o�̤���A�ڭ̴N�i�H����²�檺�d�ߥ\��F�A���U F5 ��A����u�d�ߡv�s�A�N�i�H��ܥX��Ʈw������ƤF�C

![img13](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-13.png)

�i�O�o�ɭԧڭ��ٯʤ@�Ӥ������\��A���U�ӧڭ̴N�\~�򧹦��������оǡC

### �W�\[�����d�ߥ\��

�����W�������˦��ܦh�ءA�ӧڴ��ѧڳ̱\`�Ϊ� Vue3 �������󵹦U��ѦҡA�ڭ̫e�ݬO�إߦb Vue3 �W�����A�ҥH�ڷ|�b Vue3 �s�W�@�Ӥ���������C

�o�q���оǷ|��������@�I�A�ڬO�v�B�y�k�оǡA�p�G�L�k�z�Ѫ��ܡA�i��U���ݤ@�U���㪺�d�ҨӤ��|����e�����@�I�C

#### �s�W VuePagination.js ����

��������O�@�Ӧh�ƭ������|�Ψ쪺�\��A��ĳ�i�H�s�W�@���ɮסA�N�����޿�g�b�̭��A�M��b Vue3 �N����ޤJ�C

�b /js �ؿ����s�W�@���ɮסA�ɮשR�W�� ��VuePagination.js���C

![img14](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-14.png)

�M��bVuePagination.js ���K�W�H�U�y�k�C

```JavaScript
const VuePagination = {
    data() {
        return {
            PerPage:'�C��'
            , PageTiems:'��'
            , Page:'��'
            , Times:'��'
            , Total:'�@'
            , TotalPage:'��'
        }
    }
    , props: ['pagination']
    , template: `
        <div style="text-align:right">
            <span v-for="pageNo in pagination.pages">
                <a v-if="pagination.pageNo != pageNo" v-on:click="gotoPage(pageNo)" style="cursor:pointer">
                    {{ pageNo }}
                </a>
                <label v-else>
                    {{ "[" + pageNo + "]" }}
                </label>&nbsp;
            </span>
            <span class="pager-nav">
                �i{{PerPage}}&nbsp;<input type="text" maxlength="3" style="width:35px;text-align:center;font-size:12px;" name="pageSize" :value="pagination.pageSize" v-on:change="onchange"/>
                &nbsp;{{PageTiems}}�A
                {{Total}} {{pagination.totalPage}} {{TotalPage}} {{pagination.totalCount}} {{PageTiems}}�j
                <button type="button" class="btn btn-secondary btn-sm pager-btn" style="margin-bottom: 5px;margin-right:5px;" v-on:click="gotoPage()">Q</button>
            </span>
        </div>`
    , methods: {
        gotoPage(pageNo) {
            var self = this;
            console.log(pageNo);
            // �O�_���ǤJ���w����
            if (pageNo !== undefined) {
                if (pageNo === '<') {
                    self.pagination.pageNo = parseInt(self.pagination.pageNo) - 1;
                } else if (pageNo === '>') {
                    self.pagination.pageNo = parseInt(self.pagination.pageNo) + 1;
                } else if (pageNo === '<<') {
                    self.pagination.pageNo = (Math.floor((parseInt(self.pagination.pageNo) - 10) / 10) * 10 + 1);
                } else if (pageNo === '>>') {
                    self.pagination.pageNo = (Math.floor((parseInt(self.pagination.pageNo) + 10) / 10) * 10 + 1);
                } else {
                    self.pagination.pageNo = parseInt(pageNo);
                }
            } else {
                self.pagination.pageNo = 1;
            }
            // ���w���Ƭ�0�A�۰��ܧ�1
            if (parseInt(self.pagination.pageNo) === 0 || self.IsNumeric(self.pagination.pageNo) === false) {
                self.pagination.pageNo = 1;
            }
            // ���w���Ƥj���`���ơA�۰��ܧ��`����
            self.pagination.pageNo =
                parseInt(self.pagination.pageNo) > parseInt(self.pagination.totalPage)
                    ? self.pagination.totalPage : self.pagination.pageNo;
            // ���w���Ƭ�0�A�۰��ܧ�10
            if (parseInt(self.pagination.pageSize) === 0 || self.IsNumeric(self.pagination.pageSize) === false) {
                self.pagination.pageSize = 10;
            }
            // call on even
            this.$emit('requery', { pagination: self.pagination });
        }
        , onchange(e) {
            var self = this;
            var re = /[^0-9]/;
            if (re.test(e.target.value) === false) {
                self.pagination[e.target.name] = parseInt(e.target.value);
            }
        }
        , IsNumeric(n) {
            return (n - 0) === n && n.toString().length > 0;
        }
    }
};
```

#### �ޥ� VuePagination.js ����

�b \Views\Shared\_Layout.cshtml �� JavaScript �W�\[�ޥ� VuePagination.js �ɮסC

`<script src="~/js/VuePagination.js"></script>`

![img15](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-15.png)

#### ���U VuePagination.js ����

Vue3 ����ݭn���U�b\Views\AdmAnno\Index.cshtml�ɮת� Vue.createApp({}); ���\~��A�� Vue ������U����A�W�٬� ��vue-pagination���C

`app.component('vue-pagination', VuePagination);`

![img16](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-16.png)

#### �ϥΤ�������

���U�n����A�N�i�H�b�e���W��������m�A��W��������C

`<vue-pagination v-bind:pagination="grid.pagination" v-on:requery="reQuery"></vue-pagination>`

![img20](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-20.png)

�]�������|���s�d�ߡA�ҥH�o����|�I�s�d�߭��� reQuery() �\��A���歫�s�d�ߡC

#### View �d�ߥ\��վ�

�ڭ̭��w�g�g�n�F�򥻪��d�� Query()�A�o�̦]�������\��A�վ�@�U�A�üW�\[�@�� reQuery() �������ɥi�H���s�I�s�C �վ�᪺��k�O�G

```C#
Query(reQuery) {
	var self = this;
 
	if (reQuery !== 'reQuery') {
		self.grid.pagination.pageNo = 1;
	}
 
	// �զX������
	var postData = {};
	postData['AnnoSubject'] = self.queryForm.AnnoSubject;
	postData['AnnoStatus'] = self.queryForm.AnnoStatus;
 
	// ���[����
	postData['pagination'] =  JSON.parse(JSON.stringify(self.grid.pagination));
 
	$.blockUI();
	// �ϥ� jQuery Ajax �ǰe�ܫ��
	$.ajax({
		url:'@Url.Content("~/AdmAnno/Query")',
		method:'POST',
		dataType:'json',
		data: { inModel: postData },
		success: function (datas) {
			$.unblockUI();
			if (datas.ErrMsg) {
				alert(datas.ErrMsg);
				return;
			}
			// �j�w�C��
			self.grid.datas = datas.Grid;
			self.grid.pagination = datas.pagination;
		},
		error: function (err) {
			$.unblockUI();
			alert(err.status + " " + err.statusText + '\n' + err.responseText);
		}
	});
 
}
// ���歫�d
, reQuery(emitData) {
	var self = this;
	if (emitData !== undefined) {
		self.grid.pagination = emitData.pagination;
	}
	self.Query('reQuery');
}
```

#### grid ����W�\[�����ݩ�

�b Vue3 �즳�ŧi�� data �ݩ� grid �n�W�\[�@�Ӥ����ݩʡG

```JavaScript
, pagination: {
	pages: [], pageNo: '1', pageSize: '10', totalCount: ''
}
```

![img20-1](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-20-1.png)

#### Controller �d�ߥ\��վ�

�b Controller �쥻�]�g�n�F�򥻬d�ߥ\��A�o�̦]�W�\[�����d�߫�A�]�n�վ�@�U�y�k�A�i�ΥH�U�y�k�������N�쥻���y�k�G

```C#
/// <summary>
/// �d�ߤ��i
/// </summary>
/// <param name="inModel"></param>
/// <returns></returns>
public IActionResult Query(QueryIn inModel)
{
	QueryOut outModel = new QueryOut();
	outModel.Grid = new List<AnnoModel>();
 
	// ��Ʈw�s�u�r��
	string connStr = _configuration.GetConnectionString("SqlServer");
	using (var cn = new SqlConnection(connStr))
	{
		// �D�n�d�� SQL
		string sql = @"SELECT Pkey, CONVERT(varchar(12) , AnnoDate, 111 ) as AnnoDate, AnnoSubject, AnnoContent, AnnoStatus, Case AnnoStatus when '1' then '���' when '0' then '����' end As AnnoStatusName
						FROM Announcement 
						WHERE 1=1 ";
 
		if (!string.IsNullOrEmpty(inModel.AnnoSubject))
		{
			sql += " AND AnnoSubject LIKE @AnnoSubject ";
		}
		if (!string.IsNullOrEmpty(inModel.AnnoStatus))
		{
			sql += " AND AnnoStatus = @AnnoStatus ";
		}
		sql += " ORDER BY AnnoDate desc, AnnoStatus ";
 
		object param = new
		{
			AnnoSubject = "%" + inModel.AnnoSubject + "%",
			AnnoStatus = inModel.AnnoStatus
		};
 
		// �����B�z
		int totalRowCount = 0;
		if (inModel.pagination.pageNo > 0)
		{
			string orderBy = "";
			// ���o�`����
			string totalRowSql = sql;
			if (totalRowSql.ToUpper().IndexOf("ORDER BY") > -1)
			{
				orderBy = totalRowSql.Substring(sql.ToUpper().LastIndexOf("ORDER BY"));
				totalRowSql = totalRowSql.Replace(orderBy, "");
			}
			totalRowSql = "SELECT COUNT(*) AS CNT FROM (" + totalRowSql + ") CNT_TABLE";
			var rowCnt = cn.Query(totalRowSql, param);
			foreach (var item in rowCnt)
			{
				totalRowCount = item.CNT;
			}
 
			// ���o���� SQL
			int startRow = ((inModel.pagination.pageNo - 1) * inModel.pagination.pageSize) + 1;
			int endRow = (startRow + inModel.pagination.pageSize) - 1;
			orderBy = sql.Substring(sql.ToString().ToUpper().LastIndexOf("ORDER BY"));
			sql = sql.Replace(orderBy, "");
			// �h�� Order by �O�W
			orderBy = orderBy.ToUpper().Replace("ORDER BY", "");
			StringBuilder newOrderBy = new StringBuilder();
			int index = 0;
			string[] orderBys = orderBy.Split(',');
			for (int i = 0; i < orderBys.Length; i++)
			{
				if (newOrderBy.Length > 0) { newOrderBy.Append(","); }
				string ob = orderBys[i];
				index = ob.IndexOf('.');
				if (index > -1)
				{
					newOrderBy.Append(ob.Substring(index + 1));
				}
				else
				{
					newOrderBy.Append(ob);
				}
			}
			newOrderBy.Insert(0, "ORDER BY ");
 
			sql = string.Concat(
				new object[] {
					"SELECT * FROM (SELECT *, ROW_NUMBER() OVER (", newOrderBy.ToString(), ") AS RCOUNT FROM (", sql, ") PAGE_SQL ) PAGE_SQL2 WHERE PAGE_SQL2.RCOUNT BETWEEN "
					, startRow, " AND ", endRow, " ", newOrderBy.ToString() });
		}
 
		// �ϥ� Dapper �d��
		var list = cn.Query<AnnoModel>(sql, param);
 
		// ��X����
		foreach (var item in list)
		{
			outModel.Grid.Add(item);
		}
 
		// �p�����
		outModel.pagination = this.PreparePage(inModel.pagination, totalRowCount);
	}
	return Json(outModel);
}
 
/// <summary>
/// �p�����
/// </summary>
/// <param name="model"></param>
/// <param name="TotalRowCount"></param>
/// <returns></returns>
public PaginationModel PreparePage(PaginationModel model, int TotalRowCount)
{
	List<string> pages = new List<string>();
	int pageStart = ((model.pageNo - 1) / 10) * 10;
	model.totalCount = TotalRowCount;
	model.totalPage =
			Convert.ToInt16(Math.Ceiling(
			 double.Parse(model.totalCount.ToString()) / double.Parse(model.pageSize.ToString())
			));
 
	if (model.pageNo > 10)
		pages.Add("<<");
	if (model.pageNo > 1)
		pages.Add("<");
	for (int i = 1; i <= 10; ++i)
	{
		if (pageStart + i > model.totalPage)
			break;
		pages.Add((pageStart + i).ToString());
	}
	if (model.pageNo < model.totalPage)
		pages.Add(">");
	if ((pageStart + 10) < model.totalPage)
		pages.Add(">>");
	model.pages = pages;
	return model;
}
```

�b SQL Server �������A�ڬO�����ק� SQL �y�k�A���d���\`���ơA�A�d�߻ݭn���d���ơA���C�������ɡA���|���s�p��A�u�d�߻ݭn����ƽd��C

#### ViewModel �վ�

ViewModel �������N�O�W�\[����������A�o�̧ڴN�����K�W�y�k�A�i�H�������N���e�� Model�C

```C#
public class QueryIn
{
	public string AnnoSubject { get; set; }
	public string AnnoStatus { get; set; }
 
	public PaginationModel pagination { get; set; }
}
 
public class QueryOut
{
	public List<AnnoModel> Grid { get; set; }
	public PaginationModel pagination { get; set; }
}
 
public class AnnoModel
{
	public string Pkey { get; set; }
	public string AnnoDate { get; set; }
	public string AnnoSubject { get; set; }
	public string AnnoContent { get; set; }
	public string AnnoStatus { get; set; }
	public string AnnoStatusName { get; set; }
}
 
/// <summary>
// ���� Model
/// </summary>
public class PaginationModel
{
	public List<string> pages { get; set; }
	public int pageNo { get; set; }
	public int pageSize { get; set; }
	public int totalPage { get; set; }
	public int totalCount { get; set; }
}
```

�������o�̫�A�N�i�H���դ������\��F�A�� F5 ����M�סA�d�߸�ƫ�N�|��ܤ��������G�C

![img17](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-17.png)

������ 2 ���C

![img18](https://blog.hungwin.com.tw/wp-content/uploads/2022/02/aspnet-mvc-anno-backstage-query-18.png)

�o�O�ګܱ\`�Ϊ��e�ݤ�������A���ɵ��A�C
