Async suffix in a method name now deprecated? - asp.net

VS2022, Asp.Net MVC .Net 6.0
When a function name ends with "async", the url never works. Cannot figure out why. New routing defaults, new "guidelines" enforced or simply a bug?
//works (example https://localhost:7215/home/getuserlist)
public async Task<IActionResult> GetUserList()
//doesn't work (example https://localhost:7215/home/getuserlistasync)
public async Task<IActionResult> GetUserListAsync()
//works (example https://localhost:7215/routetest)
[Route("routetest")]
public async Task<IActionResult> GetUserListAsync()

It is indeed a known behavior, albeit poorly documented. You may call it a bug if you'd like.
The original bug report can be found here, very similar to what you've described: https://github.com/dotnet/aspnetcore/issues/4849
The corresponding issue is here: https://github.com/dotnet/docs/issues/14716. The intention is to trim the suffix from the action name, because it upsets routing and link generation. They even propose a workaround:
services.AddMvc(options =>
{
options.SuppressAsyncSuffixInActionNames = false;
});
Although there are some reports that line might not work. Very confusing!
And here is the discussion that sheds some light on why the behavior you are observing isn't fixed yet: https://github.com/dotnet/aspnetcore/issues/8998. There is even a pull request that wasn't merged because there was no agreement on how to properly trim this suffix from the action name without breaking various common routines (think nameof()) and naming conventions: https://github.com/dotnet/aspnetcore/pull/39128.

Related

How to send list as parameter for search in angular service to .net core

Please Help me I need to retrieve a list of details using a list of parameters. How to achieve that from angular 10 and .net Core?
Also, Single Entries is working for search. But If I try to enter a second entry in the input field and tried to search it is not working.
The method name is GetPodForwardings.
This is the Method in angular (Service)
GetPodForwardings(conNo,newPage,pageSize)
{
return this.http.get(`${this.BaseUrl}Pod/GetConsignmentList?conNo=${conNo}&newPage=${newPage}&pageSize=${pageSize}`)
}
In .NET Controller
[Microsoft.AspNetCore.Mvc.Route("GetConsignmentList")]
[HttpGet]
public async Task<IActionResult> GetListofConsignments([FromQuery]List<long> conNo,int currentPage,int pageSize)
{
return await ProcessQuery(new GetListofConsignmentByConsignmentNoQuery(conNo,currentPage,pageSize));
}
The proper way of adding parameters to an url in Angular is to use the second options parameter of the http.get("url",options) function. Unfortunatly they don't accept arrays rightaway (there is an open github issue).
However string interpolation like you did should also work. You seem to just have the wrong format. As this is treated very framework specific look at this answer to get the right format for your case.

Is there any difference between Request.Cookies(name) and Request.Cookies.Get(name)?

As both of them can be used for retrieving cookie through name string, I would like to know if there is any difference between them.
A great way to answer a question like this yourself, for the .NET Framework, is to make use of the Microsoft Reference Source. This lets you see and navigate through the source for the .NET Framework.
Looking at this, Request.Cookies returns an HttpCookieCollection and Request.Cookies.Get is therefore a method on HttpCookieCollection.
The most useful part of the code is for the indexer on HttpCookieCollection that retrieves a cookie by name:
public HttpCookie this[String name]
{
get { return Get(name);}
}
As you can see from that, this calls into the Get(string name) method, meaning that using the Request.Cookies(name) indexer is fundamentally the same as using Request.Cookies.Get(name) as one calls the other.
It is worth mentioning that anything you see here is an implementation detail that's subject to change. You should rely on documented behaviour, not on anything you discover through digging through the code, no matter how informative and interesting it is!

SonarQube complains about using ResponseEntity with a wildcard

I use SpringBoot for REST web services development and SonarQube for static analysis.
I have a few endpoints in my application that look the following way:
#PostMapping
ResponseEntity<?> addSomething(#RequestBody Some object) {
// some code there
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
SonarQube complains about using ResponseEntity with a wildcard, reporting me a Critical issue "Generic wildcard types should not be used in return parameters".
I wonder if I should disable this verification in SonarQube or come up with something different for return type for these cases.
What do you think about it?
#PostMapping
ResponseEntity<Object> addSomething(#RequestBody Some object) {
// some code there
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
This will also remove the error. It is still very generic, but it is one of the solutions if you want to return different types based on the outcome. For instance:
#PostMapping
ResponseEntity<Object> addSomething(#RequestBody Some object) {
//Will return ResponseEntity<> with errors
ResponseEntity<Object> errors = mapValidationService(bindingResult);
if (!ObjectUtils.isEmpty(errors)) return errors;
// some code there
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
So actually i find the rule pretty self describing:
Using a wildcard as a return type implicitly means that the return value should be considered read-only, but without any way to enforce this contract.
Let's take the example of method returning a "List". Is it possible on this list to add a Dog, a Cat, ... we simply don't know. The consumer of a method should not have to deal with such disruptive questions.
https://sonarcloud.io/organizations/default/rules#rule_key=squid%3AS1452
So Actually in your case, you do not want any kind of Class in there, you specifically want an Serializable-object - for obvious reasons: it should be serialized later on
So instead of using ? it would be more suitable in your case to use Serializable. This is always case dependent, but normally you definitly expect some kind of common interface or base class as a return value. Hence that, the follow up developer, definitly knows what he can expect, and what kind of functionality he definitly can use.
Finally I've removed <?> from return value, so the code looks like the following now:
#PostMapping
ResponseEntity addSomething(#RequestBody Some object) {
// some code there
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
SonarQube doesn't complain anymore and code seems a little bit simpler now.

Retrofit and usage of absolute URLs

How can you handle in Retrofit absolute URLs for some calls?
I am using a combination of dagger, retrofit and OKHttp. I provide a #Singleton RestAdapter with the selected endpoint (Production, Staging, etc) which it is formed from the BASE URL.
#Provides
#Singleton
RestAdapter providesRestAdapter(Endpoint endpoint,
ObjectMapper jacksonObjectMapper,
Client client,
ApiRequestInterceptor headers) {
return new RestAdapter.Builder() //
.setClient(client) //
.setEndpoint(endpoint) //
.setConverter(new JacksonConverter(jacksonObjectMapper))
.setLogLevel(RestAdapter.LogLevel.FULL)
.setRequestInterceptor(headers) //
.build();
}
The problem is that the REST service, for some cases, returns the URL for the content to be loaded in ABSOLUTE format meaning something like http://someurl.com/resource?sort=ascendent and not the preferable /resouce?sort=ascendent (without the BASE_URL)
Now the question is how I can create the interface of the service to deal with such scenario?
I was thinking something like:
public interface PlaceholdersService {
#GET("{placeholderHref}")
public void getPlaceholder(#EncodedPath("placeholderHref") String placeholderHref);
}
The problem is that I am not sure if the BASE URL set in the Endpoint previously when creating the RestAdapter will be added (can't test it at the moment).
Another though was to create a new RestAdapter specially for this case with an Endpoint set to a null or empty string fixed point like Endpoints.newFixedEndpoint(null) or Endpoints.newFixedEndpoint("").
Any suggestions?
Thanks
Digging a little bit I just realised there is an open issue for this manner in Github https://github.com/square/retrofit/issues/333
It has been moved the discussion to the V2 of the library to discuss if will be supported or not in that version.
This means that if supported, won't do it for a while. Is there any suggestion or workaround you can suggest to surpass this issue for the moment?
I had a similar problem and I solved it by creating new adapter with specified URL and use an empty path in my interface. Here is my question and my own answer.
Hope it helps.

What are the concrete pros and cons of attribute-based routing vs. imperative routing in ASP.NET Web API?

Last year, the attribute-based routing was rolled into the core of ASP.NET Web API routing (http://weblogs.asp.net/scottgu/archive/2013/04/19/asp-net-web-api-cors-support-and-attribute-based-routing-improvements.aspx).
I suppose the addition implies it is somehow better than the standard imperative routing approach in app start, but apart from dev preference (which is not my concern here), what are the concrete benefits and drawbacks of the two approaches?
UPDATE: I should clarify that "it is somehow better than the" would be better said as: "it adds value over the". I mean, they would only add it if they thought it was valuable. So my question is really what are the pros/cons between the two approaches (beyond simple preference).
I wouldn't think of it as better just a different way of solving the same problem. Additions to any framework can often simply present an alternative way of doing something. It depends on how opinionated the framework designers wish to be. Typically Microsoft has always aired on the side of being somewhat un-opinionated to the point of developer confusion. But they are getting better though.
The primary benefit I see with attribute based routing, and I appreciate this may be subjective is that it's more explicit in that it brings the definition of the route closer to the target code i.e the controller action.
Given that we as developers already have enough information to wrangle in our heads when reading code, this proximity of the route definition to the executed code can only help in my opinion.
Attribute routing is more DRY. For instance:
[RoutePrefix("{controller}")]
[Route("{reviewId:int}/{action=Show}")]
public class ReviewsController : Controller {
public ActionResult Show(int reviewId) {
throw new NotImplementedException();
}
public ActionResult Edit(int reviewId) {
throw new NotImplementedException();
}
[Route("foo")]
public ActionResult Foo() {
throw new NotImplementedException();
}
}
The routes created for the above controller are:
routes.MapRoute(null, "{controller}/foo",
new { controller = "Reviews", action = "Foo" });
routes.MapRoute(null, "{controller}/{reviewId}/{action}",
new { controller = "Reviews", action = "Show" },
new { reviewId = new IntRouteConstraint() });
Note that:
In the route for Show and Edit, you didn't have to specify a default value for controller, attribute routing includes it for you.
In the route for Foo, it inherited the route prefix, and you didn't have to specify controller and action defaults.
In imperative routing makes it hard to support nested URI patterns. May times resource can contain child resource like Customer can have orders, In this case URL would be /customers/1/orders
This type of URI is difficult to create using imperative routing. Although it can be done, the results don't scale well if you have many controllers or resource types.
With attribute routing, it's trivial to define a route for this URI. You simply add an attribute to the controller action.
[Route("customers/{customerId}/orders")]
public IEnumerable<Order> GetOrdersByCustomer(int customerId) { ... }
It also solves other problems like ,
API versioning:
"/api/v1/products" would be routed to a different controller than "/api/v2/products".
/api/v1/products
/api/v2/products
Overloaded URI segments
In this example, "1" is an order number, but "pending" maps to a collection.
/orders/1
/orders/pending
Mulitple parameter types:
In this example, "1" is an order number, but "2013/06/16" specifies a date.
/orders/1
/orders/2013/06/16
Source: https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

Resources