Home > Blockchain >  Razor pages get property query naming
Razor pages get property query naming

Time:11-30

In Razor pages I would like to get a specific behaviour on how query parameters are generated, for example I would like to get this kind of url:

https://localhost:5001/admin/users?q=1&page=5

In my page model I have two properties bound for the OnGetAsync method. I tried giving the properties custom naming with

  • [Display(Name = "...")]
  • [FromQuery(Name = "...")]
  • [ModelBinding(Name = "...")]
  • [BindProperty(Name = "...")]

I even tried using combinations of this properties such as BindProperty with FromQuery. What I noticed is that when using [FromQuery] if I manually write the url in the browser the property gets the correct name but when generating it for a form or an url I could not get it with the right name.

This is my page:

public class Users : PageModel
{        

    private readonly UserManager<IdentityUser> _userManager;

    public Users(UserManager<IdentityUser> userManager)
    {
        _userManager = userManager;
    }

    [FromQuery(Name = "q")]
    [BindProperty(Name = "q", SupportsGet = true)]
    public string Search { get; set; }

    public IdentityUser CurrentUser { get; set; }
    
    [FromQuery(Name = "page")]
    [BindProperty(Name = "page", SupportsGet = true)]
    public int CurrentPage { get; set; } = 1;

    public ICollection<IdentityUser> Users { get; set; }

    public async Task OnGetAsync()
    {
        CurrentUser = await _userManager.GetUserAsync(HttpContext.User);

        IList<IdentityUser> users;
        if (string.IsNullOrWhiteSpace(Search))
        {
            users = await _userManager.Users
                .OrderBy(x => x.UserName)
                .ThenBy(x => x.Email)
                .ToListAsync();
        }
        else
        {
            users = await _userManager.Users.Where(
                    x => x.Username.Contains(Search)
                            || x.Email.Contains(Search)
                )
                .OrderBy(x => x.UserName)
                .ThenBy(x => x.Email)
                .ToListAsync();
        }
    }
}

and this is the related html:

@page
@model Pages.Users

<form method="get" class="mt-5 mb-2">
    <div class="form-row">
        <div class="form-group col">
            <label class="sr-only" asp-for="Search"></label>

            <div class="input-group">
                <div class="input-group-prepend">
                    <div class="input-group-text">
                        <i class="fa fa-search"></i>
                    </div>
                </div>

                <input asp-for="Search" class="form-control">
            </div>
        </div>
    </div>
</form>

<ul class="pagination">
    @for (var i = 1; i < Model.TotalPages; i  )
    {
        <li class="page-item @(Model.CurrentPage == i ? "active" : "")">
            <a asp-page="/Users" asp-route-search="@Model.Search" asp-route-currentpage="@i" class="page-link">@i</a>
        </li>
    }
</ul>

The generated name and id in the form input is Search instead of q

The generated url in the pagination is /users?search=aaa&currentpage=2 instead of /users?q=aaa&page=1

CodePudding user response:

The routing system in Razor Pages (which is what is used to generate URLs from the anchor tag helper) doesn't like page as a route parameter, so you will have to construct your query strings yourself, if you must have page as a key:

<a href="/[email protected]&page=@1">@i</a>

The alias passed to the name property on the BindProperty attribute only works one way. When you use input tag helpers, they generate name and id attributes based on the name of the public property that the BindAttribute has been applied to. If you want a different value in your form fields, you can override that by setting the name attribute manually.

<input asp-for="Search" name="q" >

  • Related