Rules for binding query parameters in Razor Pages
Asked Answered
U

3

12

In Razor Pages, it is quite convenient that if you were to call, for example,

http://localhost/foo?bar=42

In the corresponding model, the bar key is automatically accessible in the OnGet constructor

public IActionResult OnGet(int bar)
{
    System.Console.WriteLine($"bar is {bar}");
}

But what if the query parameter is poo?

http://localhost/foo?poo=42

then in the model, bar does not get the value 42.

So simple enough, get the variables to match the query parameter key. But what if the key is hyphenated?

http://localhost/foo?foo-bar=42

foo-bar is definitely not an acceptable variable name. How do I access this query parameter? What are the rules here?

In my specific case, I don't really have a choice but to receive these hyphenated query string parameters. Also, I'm on .net core 2.2.

Upmost answered 14/2, 2020 at 18:41 Comment(0)
T
28

I think heiphens are represented by underscores, so foo-bar becomes foo_bar, however that goes against the standard C# naming convention.

I wouldn't recommend binding query parameters as handler parameters anyway. The cleanest solution is to define a property on your PageModel like so:

// from the Microsoft.AspNetCore.Mvc namespace
[FromQuery(Name = "foo-bar")]
public string FooBar { get; set; }

This way, any time a query parameter matching that name is provided, it will always be bound. Regardless of whether or not the specific handler requested it. Then you can just access the property on your PageModel whenever you need it. So you example method becomes:

public void OnGet()
{
    System.Console.WriteLine($"bar is {FooBar}");
}
Tjirebon answered 17/2, 2020 at 19:39 Comment(2)
Why is defining query parameters as fields in PageModel the cleanest solution? They are only required in methods/routes that need them, not the whole PageModel. It doesn't make sense to make them available in the whole class.Allegedly
I guess it's really more of a matter of opinion. Especially in more complex scenarios where you may have several query parameters and multiple page actions, it's less cumbersome to simply define your query parameters once on the PageModel and then reuse them where necessary. I don't see much of a point in trying to keep the handlers as more pure methods since you'll need to access the Request/Response class properties anyway. Might as well lean all the way into the class-based approach.Tjirebon
H
12

The simplest solution in Razor Pages is to use Request.Query:

public void OnGet()
{
    var data = Request.Query["foo-bar"];
}
Handiness answered 14/2, 2020 at 22:17 Comment(2)
For some reason those indexers are not available on pages that inherit from PageModel. (type Microsoft.AspNetCore.Http.QueryString) The number of variations of types of razor pages and controllers can get confusing at times.Charpoy
@LouisSomers The correct type is is IQueryCollection, represented by the HttpRequest class's Query property.Handiness
P
0

In a standalone/WebAssembly Razor Components, it can be achieved as follows

[Parameter]
[SupplyParameterFromQuery(Name = "foo")]
public string Foo { get; init; }

See here for more info.

Padova answered 9/12, 2022 at 11:51 Comment(2)
Take care, this is only for Razor components in Blazor not applicable to Razor PagesUnbeliever
tho the answer is technically wrong, in combination with the comment it highlights the difference for Blazor and RazorPages.Larina

© 2022 - 2024 — McMap. All rights reserved.