How does FromQueryAttribute actually work and why do I need it? - c#

I'm working with some pre-existing code that uses an HttpGet endpoint to get all comments. It takes some default parameters and before each parameter it is decorated with a [FromQuery] attribute. I'm a little confused about why we need this here and what it really does for me.
There isn't much online all I found was this documentation:
(https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.fromqueryattribute?view=aspnetcore-2.2)
This doesn't answer my question though...
What is a query string?
How is it used in endpoints?
When is it that I don't need to specify this attribute? I don't see it being used very much.
[HttpGet]
[ProducesResponseType(typeof(FooResponse), 200),
public async Task<ActionResult<FooResponse>> GetAll([FromQuery]string sortColumn = "CommentId",
[FromQuery]SortDirections sortDirection = SortDirections.Asc,
[FromQuery]string filter = "",
[FromQuery]int page = 1,
[FromQuery]int pageSize = 10)
{
var data = await _mediator.Send(new GetAllComments(sortColumn, sortDirection, filter, page, pageSize));
.
.
.
return Ok(data);
}
I suspect that it has something to do with what is passed into the URL but I'm not quite sure...

The usage here is superfluous. The action would function the same without [FromQuery] being applied to all the params, as it only responds to GET requests.
What is a query string?
The query string is the portion of the URI after the ? character is applied. It constitutes a data portion of a URI versus a pure routing portion.
How is it used in endpoints?
The question here is a little tenuous, so it would be more appropriate to ask "How is it used in a request?" The answer to that it is a way to pass data along with a GET request to a particular URI. Unlike other HTTP methods, GET does not really allow a request "body". (Actually, the spec technically does allow this, but it's almost universally not implemented that way.)
When is it that I don't need to specify this attribute? I don't see it being used very much.
Again, a better question is "When do I actually need to specify this attribute?" The answer to that is basically when it's ambiguous where the data is coming from. This will almost invariably be with other HTTP methods such as POST. By default, data is expected to come from the request body there, and depending on the content type of that request body, the binding is expected to be either FromForm or FromBody, which will usually be the default for params there. (Which is the default depends on whether you're dealing with a traditional MVC-style controller or an API-style controller.) If you need to actually get a particular param from the query string instead of the body in such a scenario, then you would apply the [FromQuery] attribute to that particular param.

Since the action in your post is for GET requests only ([HttpGet]) the [FromQuery] isn't necessary - the parameters will automatically use the associated query string values.
For POST actions ([HttpPost]) this attribute specifies to grab the value from the query string as opposed to the data which was posted.

Query string is a part of the URL that comes after an ? and it provides a way to pass values as a list of key-value pairs, each pair separated by & characters. Say you have the following URL:
http://mywebsite.com/somePage?a=123&b=Hello&c=World
So the query string part int that URL corresponds to a=123&b=Hello&c=World, and the list of key-value pairs that were passed was:
a = 123
b = Hello
c = World
ASP.NET Core can bind values to variables in a lot of different ways, and one of them is by reading values from a query string and converting/assigning these values to the values of your API's methods. To specify that a parameter should come from the query string, you use the [FromQuery] attribute.
So - for instance - when you have [FromQuery]string sortColumn = "CommentId" you are basically telling it to read the sortColumn key from the query string and assign it to the sortColumn parameter of the GetAll() method, and if that "sortColumn" key is not present in the query string, it should be assigned the default "CommentId" value. It is similar to the other parameters.
So you could access that URL with something like that (you should use the correct URL to get to your GetAll method, which I can't tell with the code you have provided):
http://your-system-url-here/GetAll?page=2&pageSize=20
Which would assing the page parameter a value of 2 and the pageSize parameter a size of 20.

Related

how does Request.QueryString work?

I have a code example like this :
location.href = location.href + "/Edit?pID=" + hTable.getObj().ID; ; //aspx
parID = Request.QueryString["pID"]; //c#
it works, my question is - how ? what is the logic ?
thanks :)
The HttpRequest class represents the request made to the server and has various properties associated with it, such as QueryString.
The ASP.NET run-time parses a request to the server and populates this information for you.
Read HttpRequest Properties for a list of all the potential properties that get populated on you behalf by ASP.NET.
Note: not all properties will be populated, for instance if your request has no query string, then the QueryString will be null/empty. So you should check to see if what you expect to be in the query string is actually there before using it like this:
if (!String.IsNullOrEmpty(Request.QueryString["pID"]))
{
// Query string value is there so now use it
int thePID = Convert.ToInt32(Request.QueryString["pID"]);
}
A query string is an array of parameters sent to a web page.
This url: http://page.asp?x=1&y=hello
Request.QueryString[0] is the same as
Request.QueryString["x"] and holds a string value "1"
Request.QueryString[1] is the same as
Request.QueryString["y"] and holds a string value "hello"
The Request object is the entire request sent out to some server. This object comes with a QueryString dictionary that is everything after '?' in the URL.
Not sure exactly what you were looking for in an answer, but check out http://en.wikipedia.org/wiki/Query_string
Request.QueryString["pID"];
Here Request is a object that retrieves the values that the client browser passed to the server during an HTTP request and QueryString is a collection is used to retrieve the variable values in the HTTP query string.
READ MORE#
http://msdn.microsoft.com/en-us/library/ms524784(v=vs.90).aspx
The QueryString collection is used to retrieve the variable values in the HTTP query string.
The HTTP query string is specified by the values following the question mark (?), like this:
Link with a query string
The line above generates a variable named txt with the value "this is a query string test".
Query strings are also generated by form submission, or by a user typing a query into the address bar of the browser.
And see this sample : http://www.codeproject.com/Articles/5876/Passing-variables-between-pages-using-QueryString
refer this : http://www.dotnetperls.com/querystring
you can collect More details in google .

what is difference between Request.QueryString and Request.ServerVariables["QUERY_STRING"]

i just want to get full querystring from url.
Request.QueryString
Request.ServerVariables["QUERY_STRING"]
Can i use any one of these?
which way is preferred?
Thanks
Request.ServerVariables["QUERY_STRING"] contains the entire query string, that is everything after the question mark but before the fragment identifier #
http://msdn.microsoft.com/en-us/library/ms525396(v=vs.90).aspx
Request.QueryString Contains a collection allowing you to get individual elements.
Using following syntax:
Request.QueryString(variable)[(index)|.Count]
This collection is generated from the ServerVariables collection. The values in this collection are automaticly UrlDecoded.
So if you call Request.QueryString.ToString(), it is inherently the same as Request.ServerVariables["QUERY_STRING"], but with UrlDecoding.
So you should use this as it is safer.
Request.QueryString(variable)[(index)|.Count]
http://msdn.microsoft.com/en-us/library/ms524784(v=vs.90).aspx
http://msdn.microsoft.com/en-us/library/ms524784(v=vs.90).aspx
The QueryString collection is a parsed version of the QUERY_STRING variable in the ServerVariables collection. It enables you to retrieve the QUERY_STRING variable by name. The value of Request.QueryString(parameter) is an array of all of the values of parameter that occur in QUERY_STRING. You can determine the number of values of a parameter by calling Request.QueryString(parameter).Count. If a variable does not have multiple data sets associated with it, the count is 1. If the variable is not found, the count is 0.
To reference a QueryString variable in one of multiple data sets, you specify a value for index. The index parameter can be any value between 1 and Request.QueryString(variable).Count. If you reference one of multiple QueryString variables without specifying a value for index, the data is returned as a comma-delimited string.
When you use parameters with Request.QueryString, the server parses the parameters sent to the request and returns the specified data. If your application requires unparsed QueryString data, you can retrieve it by calling Request.QueryString without any parameters.
If you call Request.QueryString["Whatever"] than UrlDecode is automatically executed. See does Request.Querystring automatically url decode a string? . So be careful with your spaces, %20, ampersands etc.
Regards,
Michael

Requesting URL parameters in C#

The way I use to request parameters from URL is
if URL is- http://www.domain.ext/default.aspx?id=123&name=abc
In the above example we can request two parameter i.e. id and name from page default.aspx as string myid = Request["id"]; and string myname = Request["name"];
But in Facebook profile's URL it shows something of this kind.
http://www.facebook.com/john.deo or http://www.facebook.com/madcoder
Where there wont be any page name and to define name with syntax. How to request the parameters (john.deo or madcoder) from URL in C#?
This can be achieved by adding rules to an htaccess file.
RewriteRule ^([A-Za-z0-9_-]*)/$ index.php?name=$1
This rule will mean that if you type into the browser http://www.mydomain.co.uk/john you can get the value 'john' by requesting the 'name' parameter.
Those are not URL parameters, those are used to identify a resource.
You could use regex you're only objective is to get the "john.deo" in the given url
It all depends on how complex your solution is. But one easy way to do this is by using page routing.
You could register a route in your Global.asax -> Application_Start like this:
RouteTable.Routes.MapPageRoute("Route name", "requestformat", "physicalfile", checkPhysicalUrlAccess, routeValueDefaults, routeConstraints);
Then in your request format specify parameters like "{name}" and then default the name parameter in the ´routeValueDefaults´ dictionary and put a contstraint on it in the ´routeContstrains´ dictionary. The constraint can be specified by a reqular expression, so if you want the names to be all only characters you could use something like this "\w+".
The parameter then end up in the Page.RouteData["name"] collection of the physical page.

Multiple Optional Parameters with ServiceStack.Net

I'm trying to implement a service with Multiple Optional Parameters using ServiceStack.Net
At the moment my route looks like this
Routes.Add<SaveWeek>("/save/{Year}/{Week}");
I want to support uris like this:
/save/2010/12/Monday/4/Tuesday/6/Wednesday/7
ie Monday=4, Tuesday=6 and Wednesday=7
However I want the ability to ignore days i.e. the person calling the service can decide if they want to save each value for each day...
i.e. Like this with missing parameter values
?Monday=4&Wednesday=7&Friday=6
Of course one solution would be to have the following route and just pass 0 when I don't want to save the value.
Routes.Add<SaveWeek>("/save/{Year}/{Week}/{Monday}/{Tuesday}}/{Weds}/{Thurs}/{Fri}/{Sat}/{Sun}");
But..... is there a better way of achieving this functionality?
When your Route requirements start to get too complicated it will eventually become easier just to add a wild card path so you can parse the rest of the querystring yourself. i.e. in this case since the first part of the querystring remains constant you can add a wild card mapping to store the variable parts of the querystring, i.e:
Routes.Add("/save/{Year}/{Week}/{DaysString*}");
ServiceStack will still populate the partial DTO with the Year and Week fields (as well any fields that were passed in the querystring). The remaining variable parts of the url is stored in the DaysString which you are then free to parse yourself manually. So the above mapping will be able to match urls like:
/save/2010/12/Monday/4/Tuesday/6?Wednesday=7
And populate the following variables in your Request DTO:
Year: 2010
Week: 12
Wednesday: 7
DaysString: Monday/4/Tuesday/6

Routing and Controller Actions - Optional Data

I created a route in ASP.net MVC application that looks like this:
routes.MapRoute(
"ArticleRoute",
"{year}/{month}/{day}/{articleId}/{displayName}",
new { controller = "Article", action = "Details" }
);
I want a route that will be like a blog post article.
Example: http://www.foobar.com/2010/01/01/123456789/the-name-of-the-article
In my Details controller action I want to do a permanent redirect if the year, month, date and display name are not correct. I want to know the best way to write the Details() controller method.
The only field that is truly required is the articleId. If I have the article Id then the database will have what the article date and name are.
I really want to know how the controller method should look like. Do I pass in all of the values to the method or use RouteData to get them?
public ActionResult Details(int articleId, string displayName)
{
var article = */SNIP*/;
int articleYear = RouteData.Values["year"];
// etc.
DateTime articleDate = new DateTime(articleYear, articleMonth, articleDay);
string realDisplayName = article.Name.ToSeoString();
if( displayName != realDisplayName || article.Date != articleDate)
// permanent redirect to the actual article
return View();
}
OR
public ActionResult(int year, int month, int day, int articleId, string displayName)
{
var article = /*SNIP*/;
DateTime articleDate = new DateTime(year, month, day);
string realDisplayName = article.Name.ToSeoString();
if( displayName != realDisplayName || article.Date != articleDate )
// permanent redirect to the actual article
return View();
}
I think both technically work, but which is the better way?
Also: if there are any other flaws in what I am doing feel free to point them out.
I prefer RESTFul url s to query strings because they are clear, can be easily read by users and seo friendly.
In your case if you really want the url as .../2010/01/01/123456789/the-name-of-the-article the second method is the better one.
But I think there's no need to use the data/month if you are using the article id in the url.
Applications like wordpress use the /year/month/title format because if you just give the title of the article only it takes more time to query the database. But with the year and month you can speed up the db querying since you can narrow down the results and then do the title search on that result set.
I think you should use a route like .../123456789/the-name-of-the-article
See the url of this question it is Routing and Controller Actions - Optional Data in here the question title is used only for the seo purposes.
If you want the design to be pure restful then the url should be .../articles/the-name-of-the-article
I create urls like this as there are many ways to optimize the db querying (like hashing) and I LOVE pure REST.
In the case of the first example, what's the point of passing anything in if you are going to use RouteData.Values to get some values?
Also, is the var article = ... a placeholder for now until you hook up the database lookup?
From the client side, it wouldn't matter, because the URL wouldn't be any different.
On the server side, the second example looks cleaner in the code, because you don't have the lookup of RouteData.Values.
Query strings are much better than REST URLs. Routes are from early days of HTTP but was passed over for query strings for many web sites because parameters depend on route construction. Also, routes are not good for encrypting parameters when you need to.
Passing everything in is better because your parameters are strongly typed and the RouteData.Values collection is not. You are also able to cast the RouteData.Values items but that is extra code you don't have to do. This is another example of ASP.NET MVC doing code for you so you have less control if you want to do something different. Web Forms are more transparent for what the framework is actually doing, while MVC is smoke and mirrors.

Categories

Resources