pagination ruins other actions webapi - asp.net-web-api

I'm trying to implement pagination for a resource in webapi, but it ruined other action which return singleById resource.
So there are two functions for getting object/s in my api ( one single another mass but paged ) like below:
public HttpResponseMessage Get(int page,string type="mm");
public HttpResponseMessage Get(int id);
The type option is a semi search like optional filter.
I know it has conflicts i made it string id but it didn't work, i thought about a way routing each action separately or renaming them but it doesn't work cause the default route is like api/{controller}/{id} and doesn't include action names beside i don't like to have api/{controller}/post/ to be generated.

I decided to use Attribute Routing
[Route("specefiedController/{id}/single")]
to have getById action and let the other actions be as they were

Related

Why is the ID in the URL checked against the ID in the model/hidden input when posting an edit action in scaffodled code?

If you create an "MVC Controller with view, using Entity Framework" using Visual Studio scaffolded code, an Edit method is created to respond to POST. This method contains a the check if (id != movie.ID) which appears to have no real value. This same pattern is used in the ASP.NET Core 3.1 tutorial:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}
...
The docs state
The HttpGet Edit method takes the movie ID parameter, looks up the movie using the Entity Framework FindAsync method, and returns the selected movie to the Edit view. If a movie cannot be found, NotFound (HTTP 404) is returned.
What is the purpose of this check?
It appears to have no real value - the client appears to be sending both values.
Should I remove it? Should I keep it?
I think this is just a sanity check, to make sure the ID the client is posting to matches the ID in the data the client attaches in the POST request.
If the user is using the form from the view to submit the POST request, I don't see how you can get different value for the ID. But just in case of a client submitting the form without using your view, those ID values could be different. One of the examples could be using Postman.
If the POST URL is /movie/edit/7, but ID from the post body is 6 for example, your application/you will need to decide what to do. So it's you, as the developer, to determine whether it has value or not to add a check like that.
I usually just ignore the ID from the URL if it's a POST request. There shouldn't be an ID on the URL if it's well constructed RESTful API endpoint anyway. So instead, my Controller will only work with the data from the posted-back view model:
[HttpPost]
//[ValidateAntiForgeryToken] - I think ASP.NET Core MVC automatically has that on
public async Task<IActionResult> Edit(MovieViewModel vm)
{
if (ModelState.IsValid)
{
...
}
...
}
According to Microsoft
The scaffolder generates that. Feel free to remove it. In some cases it may be needed.

Laravel 5.8 - one route two different controller action

In laravel 5.8, I have have 2 type of url.
/news/{category} - > send to news controller index action, if have category bind
/news/{news} - > send to news controller details action, if have news bind
Another case abort with 404.
How can i solve this problem?
In Laravel and almost all frameworks and routing systems I'm aware of, the Route and Controller/Action relationship is 1:1. Each route can only have one controller or action to handle it.
If I understand your question correctly, you have a single route pattern of /news/{parameter}, and you want one of three things to happen:
{parameter} contains a valid Category slug. Retrieve the category and display the appropriate view.
{parameter} contains a valid Article (details) slug. Retrieve the article and display the appropriate view.
{parameter} does not contain a valid category or article slug, and thus is not found. Return a 404 error.
You'll still need only a single controller action, but you can separate the logic to make it easy to understand:
routes/web.php:
Route::get('/news/{param}', 'NewsController#index');
app/Http/Controllers/NewsController (with pseudo code):
class NewsController extends Controller
{
public function index(string $param)
{
if ($category = Category::whereSlug($param)->first()) {
// Return your category view.
}
if ($article = Article::whereSlug($param)->first()) {
// Return your article view.
}
\abort(404);
}
}
I would personally recommend against sharing a common URL structure for two different entity types like this. It opens the possibility for name conflicts (a Category and Article have the same slug) and can make the user experience confusing. (It might hurt search engine optimizations or results, also, but that's just speculation - I don't have anything to confirm or deny that.)

Redirect in controller using RedirectToAction malfunction

Normally google is my best friend but this problem I can't figure out or even understand.
I have an action in my controller that I use for selecting which follow up action in my controller to use, based on user input (see image)
This redirect work like a charm, it's when the action I'm redirected to is finished as the problem arises. In my action I fetch some much needed data for the web site. When tha data is fetched the action are supposed to redirect to a generic action, that in turn will present my view. The "middleware" action redirect correctly and it also send the parameters but the "recieving action" don't handle or recieve the parameters.
I'm totally clueless here, is it not possible to redirect to an action that in turn redirect to another action or what is the problem?
The route specification looks a bit odd.
I think it should be possibly:
[HttpGet("Customer/Device/{id}")]
public IActionResult Device(string id, bool like)
{
}
Now the URL it tried to redirect you to should work. Id from URL, and the like parameter from query.
If you want both in URL:
[HttpGet("Customer/Device/{id}/{like}")]
public IActionResult Device(string id, bool like)
{
}

Asp.net core response caching by country

I need to use use response caching for certain controller actions based on the country the request is coming from.
I have figured out how to get the country code from the request (it involves reading from a database, expensive, so I want to do this just for the actions that require a country), but I am not sure how to do the caching part.
I am thinking of writing a middleware (e.g., named CountryResolver)that will run before the response caching middleware and set the country SOMEHOW in the request and have the Response Cache middleware vary by country.
app.UseCountryResolver();
app.UseResponseCaching();
There are two main problems I am facing:
Problem 1-
I need that middleware not to run for every request, but only for some requests that are routed to country-specific actions. I am thinking of annotating such country-specific actions via a custom attribute (e.g., [CountryRequired]).
[CountryRequired]
[ResponseCache(VaryByQueryKeys = new string[] { "country"}]
public IActionResult MyAction()
{
However I don't know how the middleware can pickup the actions that have such annotation so it can decide whether to lookup the country or not.
Problem 2- "...set the country SOMEHOW in the request"
I was thinking of using VaryByQueryKeys and have the middleware set the country to a query string key named "country" BUT HttpContext.Request.Query collection is readonly. So I am not sure what other mechanism can I use for this.
Any help is very appreciated.

How to call the WebApi,Implemented with AttributeRouting for each action methods,calling it from my client and passing the Query parameters in url?

I have implemented attribute routing for each of action methods in My Webapi.
Example of action method is:-
[Route("api/DocumentApi/DeleteDocument/{fileInfoId}/{customerAccountName}")]
[HttpDelete]
public HttpResponseMessage DeleteDocument(int fileInfoId, string customerAccountName)
{
//***
//*** Some body contents
//***
}
Now i want to call the above action method from the client example( Fiddler Web debugger),or browser and want to pass the Url request in the below pattern:-
http://{localhost:9791}/api/DocumentApi/DeleteDocument?fileInfoId=12&customerAccountName="Manish"
Currently i am not able to hit the above action method by the above specified url request.
But if i use the url pattern like below:-
http://{localhost:9791}/api/DocumentApi/DeleteDocument/12/Manish
I am able to hit the above action method.But for my project requirement,I need to use the Url with query parameters only.
Please suggest me the approach,how to achieve this?
Any response will be greatly appreciated.
Route templates in Web API do not support specifying query string parameters. For your scenario, do not define fileInfoId and customerAccountName as part of your route template as doing so makes Web API to strictly look for 5 segments(the text between the / characters in your route template) in your request url...so just modify your route template to [Route("api/DocumentApi/DeleteDocument")] and keep the parameters on the actions as it is...
Use like following code :
[Route("api/DocumentApi/DeleteDocument/{fileInfoId}/{customerAccountName}")]
public HttpResponseMessage TestAction(string fileInfoId,string customerAccountName)
{

Resources