ASP.NET Core:表单提交操作中的路由参数

huangapple go评论65阅读模式
英文:

ASP.NET Core: route parameter on a form submit action

问题

以下是要翻译的内容:

I have an Index Razor page implemented with paging based on the tutorial here. I also implemented a user-selectable page sizing (details not shown here for brevity as it is not applicable to this problem) as well which I all have working. I am attempting to add the search functionality from the same page [here][2]. I have the search functionality working as well.

What I am struggling to get working is routing the current page size to the Get method when the search button is clicked.

Here is my search form from the index page:

<form asp-page="./Index" asp-route-pageSize="@Model.Logs.PageSize" method="get">
<div class="form-actions no-color">
<p>
Find by @nameof(Data.Audit.Log.Level):
<select asp-for="@Model.LevelFilter" asp-items="Html.GetEnumSelectList<Microsoft.Extensions.Logging.LogLevel>()">
<option selected="selected" value="@Model.LevelFilter">Please select</option>
</select>
<input type="submit" value="Search" class="btn btn-primary" asp-route-pageSize="@Model.Logs.PageSize" /> |
<a asp-page="./Index" asp-route-pageSize="@Model.Logs.PageSize">Back to full List</a>
</p>
</div>
</form>

And here is the Get method on the Index page:

public PaginatedList<Data.Audit.Log> Logs { get; set; }

public LogLevel? LevelFilter { get; set; }

public async Task OnGetAsync(int? pageIndex, int? pageSize, int? prevPageSize, LogLevel? levelFilter)
{
LevelFilter = levelFilter;

if (prevPageSize != null && pageSize != null && pageIndex != null && pageIndex > 1)
{
pageIndex = PaginatedList<Data.Audit.Log>.CalculateNewPageIndex(pageIndex.Value, prevPageSize.Value, pageSize.Value);
}

var query = DbContext.Logs.AsQueryable();

if(levelFilter != null)
{
query = query.Where(x => x.Level == levelFilter.ToString());
}

Logs = await PaginatedList<Data.Audit.Log>.CreateAsync(query.OrderByDescending(x => x.Logged).AsNoTracking(), pageIndex ?? 1, pageSize ?? _defaultPageSize);
}

As you can see in the .cshtml markup, I have tried putting the asp-route-pageSize on the form, input, and even the 'a' tag in the form. The html seems to be generated correctly:

[![enter image description here][3]][3]

The "Back for full List" behaves correctly and maintains the pageSize, however the Search button loses it. The only query parameter in this scenario added is the levelFilter. Any ideas what I am missing / doing wrong?

UPDATE: Here's the entire .cshtml for reference:

<h1>@ViewData["Title"]</h1>

<form asp-page="./Index" asp-route-pageSize="@Model.Logs.PageSize" method="get">
<div class="form-actions no-color">
<p>
Find by @nameof(Data.Audit.Log.Level):
<select asp-for="@Model.LevelFilter" asp-items="Html.GetEnumSelectList<Microsoft.Extensions.Logging.LogLevel>()">
<option selected="selected" value="@Model.LevelFilter">Please select</option>
</select>
<input type="submit" value="Search" class="btn btn-primary" asp-route-pageSize="@Model.Logs.PageSize" /> |
<a asp-page="./Index" asp-route-pageSize="@Model.Logs.PageSize">Back to full List</a>
</p>
</div>
</form>

<table class="usa-table usa-table--striped usa-table--borderless">
<thead>
<tr>
<th scope="col">
@Html.DisplayNameFor(model => model.Logs[0].Logged)
</th>
<th scope="col">
@Html.DisplayNameFor(model => model.Logs[0].Level)
</th>
<th scope="col">
@Html.DisplayNameFor(model => model.Logs[0].Message)
</th>
<th scope="col">
@Html.DisplayNameFor(model => model.Logs[0].UserName)
</th>
<th scope="col">
@Html.DisplayNameFor(model => model.Logs[0].Category)
</th>
<th>
Action
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Logs)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Logged)
</td>
<td>
@Html.DisplayFor(modelItem => item.Level)
</td>
<td style="white-space:normal">
@Html.DisplayFor(modelItem => item.Message)
</td>
<td>
@Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
@Html.DisplayFor(modelItem => item.Category)
</td>
<td>
<a asp-page="./Details" asp-route-id="@item.Id" class="usa-button usa-button--outline">Details</a>
</td>
</tr>
}
</tbody>
</table>

<div id="pagingDiv" class="pages-div">
@if (Model.Logs.HasPrevPage)
{
<a asp-page="./Index" asp-route-pageIndex="@(Model.Logs.PageIndex - 1)" asp-route-pageSize="@Model.Logs.PageSize" asp-route-levelFilter="@Model.LevelFilter" class="usa-button usa-button--outline">Prev</a>
}

@if (Model.Logs.ShowFirstPage)
{
<a asp-page="./Index" asp-route-pageIndex="@(1)" asp-route-pageSize="@Model.Logs.PageSize" asp-route-levelFilter="@Model.LevelFilter" class="usa-button usa-button--outline">1</a>
<div class="inline-div">...</div>
}

@for (int i = Model.Logs.MinPage; i <= Model.Logs.MaxPage; i++)
{
if (Model.Logs.PageIndex == i)
{
<div class="non-button usa-button usa-button--active">@i.ToString()</div>
}
else
{
<a asp-page="./Index" asp-route-pageIndex="@i" asp-route-pageSize="@Model.Logs.PageSize" asp-route-levelFilter="@Model.LevelFilter" class="usa-button usa-button--outline">@i.ToString()</a>
}
}

@if (Model.Logs.ShowLastPage)
{
<div class="inline-div">...</div>
<a asp-page="./Index" asp-route-pageIndex="@Model.Logs.TotalPages" asp-route-pageSize="@Model.Logs.PageSize" asp-route-levelFilter="@Model.LevelFilter" class="usa-button usa-button--outline">@Model.Logs.TotalPages</a>
}

@if (Model.Logs.HasNextPage)
{
<a asp-page="./Index" asp-route-pageIndex="@(Model.Logs.PageIndex + 1)" asp-route-pageSize="@Model.Logs.PageSize" asp-route-levelFilter="@Model.LevelFilter" class="usa-button usa-button--outline">Next</a>
}
</div>
<div id="pagingDiv" class="records-per-page-div">
@foreach(var i in Model.Logs.PageSizes)
{
if (Model.Logs.PageSize == i)
{
<div class="non-button usa-button usa-button--active">@i.ToString()</div>
}
else
{
<a asp-page="./Index" asp-route-pageIndex="@Model.Logs.PageIndex" asp-route-pageSize="@i" asp-route-prevPageSize="@Model.Logs.PageSize"
asp-route-levelFilter="@

<details>
<summary>英文:</summary>

I have an `Index` Razor page implemented with paging based on the tutorial [here][1]. I also implemented a user-selectable page sizing (details not shown here for brevity as it is not applicable to this problem) as well which I all have working. I am attempting to add the search functionality from the same page [here][2]. I have the search functionality working as well. 

What I am struggling to get working is routing the current page size to the Get method when the search button is clicked. 

Here is my search form from the index page:

    &lt;form asp-page=&quot;./Index&quot; asp-route-pageSize=&quot;@Model.Logs.PageSize&quot; method=&quot;get&quot;&gt;
    &lt;div class=&quot;form-actions no-color&quot;&gt;
        &lt;p&gt;
            Find by @nameof(Data.Audit.Log.Level):
            &lt;select asp-for=&quot;@Model.LevelFilter&quot; asp-items=&quot;Html.GetEnumSelectList&lt;Microsoft.Extensions.Logging.LogLevel&gt;()&quot;&gt;
                &lt;option selected=&quot;selected&quot; value=&quot;@Model.LevelFilter&quot;&gt;Please select&lt;/option&gt;
            &lt;/select&gt;
            &lt;input type=&quot;submit&quot; value=&quot;Search&quot; class=&quot;btn btn-primary&quot; asp-route-pageSize=&quot;@Model.Logs.PageSize&quot; /&gt; |
            &lt;a asp-page=&quot;./Index&quot; asp-route-pageSize=&quot;@Model.Logs.PageSize&quot;&gt;Back to full List&lt;/a&gt;
        &lt;/p&gt;
    &lt;/div&gt;
    &lt;/form&gt;

And here is the `Get` method on the `Index` page:

    public PaginatedList&lt;Data.Audit.Log&gt; Logs { get; set; }

    public LogLevel? LevelFilter { get; set; }

    public async Task OnGetAsync(int? pageIndex, int? pageSize, int? prevPageSize, LogLevel? levelFilter)
    {
        LevelFilter = levelFilter;

        if (prevPageSize != null &amp;&amp; pageSize != null &amp;&amp; pageIndex != null &amp;&amp; pageIndex &gt; 1)
        {
            pageIndex = PaginatedList&lt;Data.Audit.Log&gt;.CalculateNewPageIndex(pageIndex.Value, prevPageSize.Value, pageSize.Value);
        }

        var query = DbContext.Logs.AsQueryable();

        if(levelFilter != null)
        {
            query = query.Where(x =&gt; x.Level == levelFilter.ToString());
        }

        Logs = await PaginatedList&lt;Data.Audit.Log&gt;.CreateAsync(query.OrderByDescending(x =&gt; x.Logged).AsNoTracking(), pageIndex ?? 1, pageSize ?? _defaultPageSize);
    }

As you can see in the `.cshtml` markup, I have tried putting the `asp-route-pageSize` on the form, input, and even the &#39;a&#39; tag in the form. The html seems to be generated correctly:

[![enter image description here][3]][3]

The &quot;Back for full List&quot; behaves correctly and maintains the pageSize, however the Search button loses it. The only query parameter in this scenario added is the levelFilter. Any ideas what I am missing / doing wrong?

**UPDATE**: Here&#39;s the entire `.cshtml` for reference:

    &lt;h1&gt;@ViewData[&quot;Title&quot;]&lt;/h1&gt;

    &lt;form asp-page=&quot;./Index&quot; asp-route-pageSize=&quot;@Model.Logs.PageSize&quot; method=&quot;get&quot;&gt;
        &lt;div class=&quot;form-actions no-color&quot;&gt;
            &lt;p&gt;
                Find by @nameof(Data.Audit.Log.Level):
                &lt;select asp-for=&quot;@Model.LevelFilter&quot; asp-items=&quot;Html.GetEnumSelectList&lt;Microsoft.Extensions.Logging.LogLevel&gt;()&quot;&gt;
                    &lt;option selected=&quot;selected&quot; value=&quot;@Model.LevelFilter&quot;&gt;Please select&lt;/option&gt;
                &lt;/select&gt;
                &lt;input type=&quot;submit&quot; value=&quot;Search&quot; class=&quot;btn btn-primary&quot; asp-route-pageSize=&quot;@Model.Logs.PageSize&quot; /&gt; |
                &lt;a asp-page=&quot;./Index&quot; asp-route-pageSize=&quot;@Model.Logs.PageSize&quot;&gt;Back to full List&lt;/a&gt;
            &lt;/p&gt;
        &lt;/div&gt;
    &lt;/form&gt;

    &lt;table class=&quot;usa-table usa-table--striped usa-table--borderless&quot;&gt;
        &lt;thead&gt;
            &lt;tr&gt;
                &lt;th scope=&quot;col&quot;&gt;
                    @Html.DisplayNameFor(model =&gt; model.Logs[0].Logged)
                &lt;/th&gt;
                &lt;th scope=&quot;col&quot;&gt;
                    @Html.DisplayNameFor(model =&gt; model.Logs[0].Level)
                &lt;/th&gt;
                &lt;th scope=&quot;col&quot;&gt;
                    @Html.DisplayNameFor(model =&gt; model.Logs[0].Message)
                &lt;/th&gt;
                &lt;th scope=&quot;col&quot;&gt;
                    @Html.DisplayNameFor(model =&gt; model.Logs[0].UserName)
                &lt;/th&gt;
                &lt;th scope=&quot;col&quot;&gt;
                    @Html.DisplayNameFor(model =&gt; model.Logs[0].Category)
                &lt;/th&gt;
                &lt;th&gt;
                    Action
                &lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            @foreach (var item in Model.Logs)
            {
                &lt;tr&gt;
                    &lt;td&gt;
                        @Html.DisplayFor(modelItem =&gt; item.Logged)
                    &lt;/td&gt;
                    &lt;td&gt;
                        @Html.DisplayFor(modelItem =&gt; item.Level)
                    &lt;/td&gt;
                    &lt;td style=&quot;white-space:normal&quot;&gt;
                        @Html.DisplayFor(modelItem =&gt; item.Message)
                    &lt;/td&gt;
                    &lt;td&gt;
                        @Html.DisplayFor(modelItem =&gt; item.UserName)
                    &lt;/td&gt;
                    &lt;td&gt;
                        @Html.DisplayFor(modelItem =&gt; item.Category)
                    &lt;/td&gt;
                    &lt;td&gt;
                        &lt;a asp-page=&quot;./Details&quot; asp-route-id=&quot;@item.Id&quot; class=&quot;usa-button usa-button--outline&quot;&gt;Details&lt;/a&gt;
                    &lt;/td&gt;
                &lt;/tr&gt;
            }
        &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;div id=&quot;pagingDiv&quot; class=&quot;pages-div&quot;&gt;
        @if (Model.Logs.HasPrevPage)
        {
            &lt;a asp-page=&quot;./Index&quot; asp-route-pageIndex=&quot;@(Model.Logs.PageIndex - 1)&quot; asp-route-pageSize=&quot;@Model.Logs.PageSize&quot; asp-route-levelFilter=&quot;@Model.LevelFilter&quot; class=&quot;usa-button usa-button--outline&quot;&gt;Prev&lt;/a&gt;
        }

        @if (Model.Logs.ShowFirstPage)
        {
            &lt;a asp-page=&quot;./Index&quot; asp-route-pageIndex=&quot;@(1)&quot; asp-route-pageSize=&quot;@Model.Logs.PageSize&quot; asp-route-levelFilter=&quot;@Model.LevelFilter&quot; class=&quot;usa-button usa-button--outline&quot;&gt;1&lt;/a&gt;
            &lt;div class=&quot;inline-div&quot;&gt;...&lt;/div&gt;
        }

        @for (int i = Model.Logs.MinPage; i &lt;= Model.Logs.MaxPage; i++)
        {
            if (Model.Logs.PageIndex == i)
            {
                &lt;div class=&quot;non-button usa-button usa-button--active&quot;&gt;@i.ToString()&lt;/div&gt;
            }
            else
            {
                &lt;a asp-page=&quot;./Index&quot; asp-route-pageIndex=&quot;@i&quot; asp-route-pageSize=&quot;@Model.Logs.PageSize&quot; asp-route-levelFilter=&quot;@Model.LevelFilter&quot; class=&quot;usa-button usa-button--outline&quot;&gt;@i.ToString()&lt;/a&gt;
            }
        }

        @if (Model.Logs.ShowLastPage)
        {
            &lt;div class=&quot;inline-div&quot;&gt;...&lt;/div&gt;
            &lt;a asp-page=&quot;./Index&quot; asp-route-pageIndex=&quot;@Model.Logs.TotalPages&quot; asp-route-pageSize=&quot;@Model.Logs.PageSize&quot; asp-route-levelFilter=&quot;@Model.LevelFilter&quot; class=&quot;usa-button usa-button--outline&quot;&gt;@Model.Logs.TotalPages&lt;/a&gt;
        }

        @if (Model.Logs.HasNextPage)
        {
            &lt;a asp-page=&quot;./Index&quot; asp-route-pageIndex=&quot;@(Model.Logs.PageIndex + 1)&quot; asp-route-pageSize=&quot;@Model.Logs.PageSize&quot; asp-route-levelFilter=&quot;@Model.LevelFilter&quot; class=&quot;usa-button usa-button--outline&quot;&gt;Next&lt;/a&gt;
        }
    &lt;/div&gt;
    &lt;div id=&quot;pagingDiv&quot; class=&quot;records-per-page-div&quot;&gt;
        @foreach(var i in Model.Logs.PageSizes)
        {
            if (Model.Logs.PageSize == i)
            {
                &lt;div class=&quot;non-button usa-button usa-button--active&quot;&gt;@i.ToString()&lt;/div&gt;
            }
            else
            {
                &lt;a asp-page=&quot;./Index&quot; asp-route-pageIndex=&quot;@Model.Logs.PageIndex&quot; asp-route-pageSize=&quot;@i&quot; asp-route-prevPageSize=&quot;@Model.Logs.PageSize&quot;
                    asp-route-levelFilter=&quot;@Model.LevelFilter&quot; class=&quot;usa-button usa-button--outline&quot;&gt;@i.ToString()&lt;/a&gt;
            }
        }
    &lt;/div&gt;

  [1]: https://learn.microsoft.com/en-us/aspnet/core/data/ef-rp/sort-filter-page?view=aspnetcore-7.0#add-paging
  [2]: https://learn.microsoft.com/en-us/aspnet/core/data/ef-rp/sort-filter-page?view=aspnetcore-7.0#add-filtering
  [3]: https://i.stack.imgur.com/0KTJo.png

</details>


# 答案1
**得分**: 2

在[@pcalkins][1]的大力帮助下,这里是正确的答案。我不得不添加隐藏的输入标签,映射到Model.Logs.PageSize,并给它命名为我想要的查询字符串参数:

```html
<input asp-for="@Model.Logs.PageSize" name="pageSize" type="hidden" />

这是完整的表单:

<form asp-page="./Index" method="get">
    <div class="form-actions no-color">
        <input asp-for="@Model.Logs.PageSize" name="pageSize" type="hidden" />
        <p>
            按@nameof(Data.Audit.Log.Level)查找:
            <select asp-for="@Model.LevelFilter" asp-items="Html.GetEnumSelectList<Microsoft.Extensions.Logging.LogLevel>()">
                <option selected="selected" value="@Model.LevelFilter">请选择</option>
            </select>
            <input type="submit" value="搜索" class="btn btn-primary" /> |
            <a asp-page="./Index" asp-route-pageSize="@Model.Logs.PageSize">返回到完整列表</a>
        </p>
    </div>
</form>
英文:

With much help from @pcalkins, here is the correct answer. I had to add the hidden input tag mapped to the Model.Logs.PagSize as well as give it the name of the parameter I wanted on the query string:

&lt;input asp-for=&quot;@Model.Logs.PageSize&quot; name=&quot;pageSize&quot; type=&quot;hidden&quot; /&gt;

Here's the full form:

&lt;form asp-page=&quot;./Index&quot; method=&quot;get&quot;&gt;
&lt;div class=&quot;form-actions no-color&quot;&gt;
&lt;input asp-for=&quot;@Model.Logs.PageSize&quot; name=&quot;pageSize&quot; type=&quot;hidden&quot; /&gt;
&lt;p&gt;
Find by @nameof(Data.Audit.Log.Level):
&lt;select asp-for=&quot;@Model.LevelFilter&quot; asp-items=&quot;Html.GetEnumSelectList&lt;Microsoft.Extensions.Logging.LogLevel&gt;()&quot;&gt;
&lt;option selected=&quot;selected&quot; value=&quot;@Model.LevelFilter&quot;&gt;Please select&lt;/option&gt;
&lt;/select&gt;
&lt;input type=&quot;submit&quot; value=&quot;Search&quot; class=&quot;btn btn-primary&quot; /&gt; |
&lt;a asp-page=&quot;./Index&quot; asp-route-pageSize=&quot;@Model.Logs.PageSize&quot;&gt;Back to full List&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/form&gt;

huangapple
  • 本文由 发表于 2023年8月4日 01:26:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76830347.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定