# 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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET 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?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
