How to remove the GetAll/Get/Create/Delete/Update from the auto generated controllers routes based on an AsyncCrudAppService in aspnetboilerplate? - aspnetboilerplate

By creating an application service which is based on an AsyncCrudAppService, you will get the auto generated api controllers for it, however, the routes are not really like a Rest API. If the entity name is "Project", the routes will be
/api/services/app/Projects/GetAll [GET]
/api/services/app/Projects/Get [GET]
/api/services/app/Projects/Create [POST]
/api/services/app/Projects/Update [PATCH]
/api/services/app/Projects/Delete [Delete]
But I would like to see somthing like:
/api/services/app/Projects [GET]
/api/services/app/Projects/{id} [GET]
/api/services/app/Projects [POST]
/api/services/app/Projects/{id} [PATCH]
/api/services/app/Projects/{id} [Delete]
I know that I could do something like this, but of course I don't like it:
[Route("api/services/app/projects")]
[HttpPost]
public override Task<ProjectDto> CreateAsync(CreateProjectDto input){
return base.CreateAsync(input);
}
Is there a better solution for this? Thanks

just use [Obsolete] attribute top of function, and then removed from swagger.

Related

AttributeRouting conflicting parameter route with string route

I have two controllers, ItemsController and SingleItemController which both inherit from ApiController. Both have RoutePrefix items/inventory defined on the controllers, like so:
[RoutePrefix("items/inventory")]
I'm using AttributeRouting in Web API 2.2.
In SingleItemController I have the following route:
[Route("{itemReference}")]
[HttpGet]
public ItemDTO GetItem(string itemReference)
In ItemsController I have the following route:
[Route("all")]
[HttpGet]
public List<ItemDTO> GetAllItems(DateTime dateFrom, DateTime dateTo)
When I try to hit the /items/inventory/all?dateFrom=2015-09-06&dateTo=2015-09-12 route, I get the following error:
Multiple controller types were found that match the URL. This can
happen if attribute routes on multiple controllers match the requested
URL. The request has found the following matching controller types:
ItemAPI.Controllers.ItemsController
ItemAPI.Controllers.SingleItemController
So {itemReference} route is conflicting with all route. Why is this? I would think that it reserves first all route and then allows an optional string route.
This is because it can't decide whether "all" is an item reference.
I had a similar issue recently where I had a controller with an "admin" route prefix.
To get round the issue I put a constraint on the parameter to ignore the word "admin".
So in your case you could do the following to ignore the word "all":
[Route("{itemReference:regex(^(?!all))})]

How to map different HTTP methods on the same url to different controllers?

I have my API for a small part of my application split over two controllers, because of (external) requirements on the casing of JSON data in the API (some requests should use camelCasing, while others should use PascalCasing).
Now, I have a url that I want to map with PascalCasing for GET, but camelCasing for PUT, so I tried the following:
[PascalCasing] // custom attribute, part of our code
// We configure all controllers that *don't* have this to use
// camelCasing
public class PascalCasedController : ApiController
{
[HttpGet]
[Route("url/to/my/resource/{id}")]
public IHttpActionResult(int id)
{
return Ok(GetResource(id));
}
}
public class CamelCasedController : ApiController
{
[HttpPut]
[Route("url/to/my/resource/{id}")]
public IHttpActionResult(int id, Resource resource)
{
SaveResource(id, resource);
return Ok();
}
}
The GET request works as expected, but if I try to PUT something there with Fiddler, I get the following error message:
Multiple controller types were found that match the URL. This can happen if attribute routes on multiple controllers match the requested URL.
The request has found the following matching controller types:
MyProject.PascalCaseController
MyProject.CamelCaseController
I realize this is probably because WebAPI maps routes to controllers first and actions next, but if HTTP methods are considered, there really isn't any ambiguity here. Is there any way that I can tell WebAPI how to do this, without having to have the methods in the same controller?
#Tomas - There's an interface "System.Web.Http.Dispatcher.IHttpControllerSelector" exposed in System.Web.Http assembly. You can use that interface and create your own HttpControllerSelector. You can then replace the DefaultControllerSelector with your custom controller selector in the HttpConfiguration during AreaRegistration.
httpConfig.Services.Replace(typeof(IHttpControllerSelector), new CustomControllerSelector(services.GetHttpControllerSelector()));
In this custom controller selector you can write your own implementation of SelectController() method of IHttpControllerSelector in which you can call GetControllerMapping() method of IHttpControllerSelector. This will give you the list of all the controllers registered. For every controller you can check for the DeclaredMethods and check for the CustomAttributes for each of the DeclaredMethods. In your case it will be either HttpGetAttribute or HttpPutAttribute.
Check the Method type of the incoming HttpRequestMessage (GET/PUT) and compare it against the value of the CustomAttributes. If you find a match of the combination of incoming request URL and the the respective Http Verb then you take that HttpControllerDiscriptor and return it from the SelectController() method..
This will allow you to have same URL with different methods in two different controllers.

How to make laravel routing like in wordpress?

Strandart url - site.com/controller/func/parametr
You can make such constructions urls:
site.com/category/category1/post1
site.com/category/category1/post2
site.com/category/category2/post1
I would like to:
site.com/category1/post1
site.com/category2/post1
It is possible if i make controller for each category, but is so messy.
You can do it just be defining a route like this
Route::get('/{cat}/{title}',array('uses' => 'PostsController#showPost'));
And then use the parameters in the action
public function showPost($cat, $title){
// you can find category and post by titles and show the post
}

Laravel - Route::resource vs Route::controller

I read the docs on the Laravel website, Stack Overflow, and Google but still don't understand the difference between Route::resource and Route::controller.
One of the answers said Route::resource was for crud. However, with Route::controller we can accomplish the same thing as with Route::resource and we can specify only the needed actions.
They appear to be like siblings:
Route::controller('post','PostController');
Route::resource('post','PostController');
How we can choose what to use? What is good practice?
RESTful Resource controller
A RESTful resource controller sets up some default routes for you and even names them.
Route::resource('users', 'UsersController');
Gives you these named routes:
Verb Path Action Route Name
GET /users index users.index
GET /users/create create users.create
POST /users store users.store
GET /users/{user} show users.show
GET /users/{user}/edit edit users.edit
PUT|PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy
And you would set up your controller something like this (actions = methods)
class UsersController extends BaseController {
public function index() {}
public function show($id) {}
public function store() {}
}
You can also choose what actions are included or excluded like this:
Route::resource('users', 'UsersController', [
'only' => ['index', 'show']
]);
Route::resource('monkeys', 'MonkeysController', [
'except' => ['edit', 'create']
]);
API Resource controller
Laravel 5.5 added another method for dealing with routes for resource controllers. API Resource Controller acts exactly like shown above, but does not register create and edit routes. It is meant to be used for ease of mapping routes used in RESTful APIs - where you typically do not have any kind of data located in create nor edit methods.
Route::apiResource('users', 'UsersController');
RESTful Resource Controller documentation
Implicit controller
An Implicit controller is more flexible. You get routed to your controller methods based on the HTTP request type and name. However, you don't have route names defined for you and it will catch all subfolders for the same route.
Route::controller('users', 'UserController');
Would lead you to set up the controller with a sort of RESTful naming scheme:
class UserController extends BaseController {
public function getIndex()
{
// GET request to index
}
public function getShow($id)
{
// get request to 'users/show/{id}'
}
public function postStore()
{
// POST request to 'users/store'
}
}
Implicit Controller documentation
It is good practice to use what you need, as per your preference. I personally don't like the Implicit controllers, because they can be messy, don't provide names and can be confusing when using php artisan routes. I typically use RESTful Resource controllers in combination with explicit routes.
For route controller method we have to define only one route. In get or post method we have to define the route separately.
And the resources method is used to creates multiple routes to handle a variety of Restful actions.
Here the Laravel documentation about this.
i'm using Laravel 8 in my project
and in my route file web.php
i add this route
Route::controller(SitesController::class)->group(function() {
Route::get('index', 'index')->name('index');
}
in the Route::controller group we pass controller name we will use
inside the group we define the route we'll use as below syntax
Route::method-used('prefix in the URL', 'function used in the specified controller ')->name(); if the name not used in your code just delete it

405 method not allowed in ASP.Net Web API Controller

I've looked around to try to find some posts on this and there are many rather a lot but none that address my specific question (that I could find).
In my Api Controller there are many other methods with "GET" which are working fine but when I added a new method it's returning 405 method not allowed message
[GET("GetNames/{Id}/{Age}")]
public List<Names> Names(long Id, string Age)
{
...
...
}
but when I put [System.Web.Http.HttpGet] on my method it's start working.
[System.Web.Http.HttpGet]
[GET("GetNames/{Id}/{Age}")]
public List<Names> Names(long Id, string Age)
{
...
...
}
Can anyone please explain me what I am doing wrong or this is the correct way. I found almost same question MVC AttributeRouting With.. and 405 when using.. but still confused.
Web API by default assumes the action to be of verb POST if verbs like "Get", "Post", "Put", "Delete" are not specified.
Also you have given [GET("GetNames/{Id}/{Age}")] attribute explicitly, and its a object of GETAttribute.
Action selector looks for attributes from System.Web.Http namespace like HttpGet,HttpGetAttribute, HttpPostAttribute, HttpPutAttribute etc.
So remove [GET("GetNames/{Id}/{Age}")].
do not remove [HttpGet]
Create a custom route in app_start/WebApiConfig.cs file for this action if needed.
Hope this helps.
if you have
using System.Web.Mvc;
remove it and add
using System.Web.Http;

Resources