Access to controller method - c#

I have Controller with some method GET :
public class TestController : ApiController
{
public List<T> Get(){...}
[ActionName("GetById")]
public T Get(int id){...}
}
Can i access second Get method as /Get?id=1 even if i have different ActionName?
ActionName for generating cache with different names

Updated because my previous answer was related to standard MVC controllers not Web API because that is what the ActionName attribute is for. I am not sure what if anything it would do on a web api controller. Without attributes or a change from the deault routing your actions would have the following routes "/api/test/" Get() "/api/test/id" Get(int id) where id is an int.
If you want more flexibility MVC5 supports attribute routing

Related

Is there an OOTB component to get routes from controller names and their methods?

I would like to list all the available endpoints a controller provides.
Is it possible to access the component(s) .NET uses to generate these routes (by, for instance providing it a type or controller name (string))?
The methods/verbs (so, POST, GET) are not even that important for my scenario, just the routes themselves.
Example
Please, take a look on the below ASP.NET Core code.
[ApiController]
[Route("[controller]")
public class HomeController : ControllerBase
{
[HttpGet("additional")]
public async Task<IActionResult> Whatever()
{
// ...
}
}
So, the method will be exposed as a GET endpoint on the URL of Home/additional.

MVC Attribute Routing with query parameter not working

I am trying to combine my UI project and WebAPI project into one to make it more maintainable, however I am getting an error with the routing as below:
{
"Message": "No HTTP resource was found that matches the request URI 'http://localhost:64182/api/v1/business?id=101'.",
"MessageDetail": "No type was found that matches the controller named 'api'."
}
I have added attribute routing on the method to get it to work, but it only works with the following url:
MVC ACtion:
[HttpGet, Route("api/v1/business/{id:int}")]
public IHttpActionResult Get([FromUri]int? id)
{
....
}
http://localhost:64182/api/v1/business/101
The intended url signature cannot change and it should still use the query parameter:
http://localhost:64182/api/v1/business?id=101
In the Route attribute, I cannot add a question mark because it is not allowed.
The system is already being used by many users and I cannot change the signature unfortunately otherwise this would break their systems.
How can I get this to work or what Route template can I use to include the query parameter?
I think the attribute [FromUri] is deprecated. Try using [FromRoute]. Also, I would structure my routing from the controller class.
The following is for http://localhost:64182/api/v1/business/101
[Route("api/v1/[controller]")]
[ApiController]
public class Business : ControllerBase
{
[HttpGet("/{id:int}")]
public async Task<ActionResult<YourBusinessDto>> Get([FromRoute] int id)
{
//Your code to get your business dto here.
}
}
The following is for http://localhost:64182/api/v1/business?id=101
[Route("api/v1/[controller]")]
[ApiController]
public class Business : ControllerBase
{
[HttpGet]
public async Task<ActionResult<YourBusinessDto>> Get([FromQuery] int id)
{
//Your code to get your business dto here.
}
}
In our order collection, each order has a unique identifier. We can go to the collection and request it by "id". Typical RESTful best practice, this can be retrieved by its route, for example "api/orders/1"
//api/orders/1
[HttpGet("api/orders/{id}")]
public string test1([FromRoute]int id)
{
return "test1";
}
This attribute will instruct the ASP.NET Core framework to treat this operation as a handler for the HTTP GET verb and handle routing. We provide an endpoint template as an attribute parameter. This template is used as the route that the framework will use to match incoming requests. In this template, the {id}​​ value corresponds to the route part as the "id" parameter. The FromRoute attribute tells the framework to look up the "id" value in the route (URL) and provide it as the id parameter.
In addition, we can easily write it to use the FromQuery property. This then instructs the framework to predict a query string with an "identifier" name and corresponding integer value. Then pass the value as the id parameter to the operation. Everything else is the same.
However, the most common method is the aforementioned FromRoute usage-where the identifier is part of the URI
//api/orders?id=1
[HttpGet("api/v1")]
public string test2([FromQuery]int id)
{
return "test2";
}
In addition, you can refer to this detailed article for more attribute usage, which may be helpful to you:
https://www.dotnetcurry.com/aspnet/1390/aspnet-core-web-api-attributes

Multiple controller types were found error in c# web api 2.0

Why this doesn't work? I get error: System.InvalidOperationException: Multiple controller types were found that match the URL. This can happen if attribute routes on multiple controllers match the requested URL.
public class ConfigUpdateController: ApiController
{
[HttpPut]
[Route("api/device/{serial}/config")]
public IHttpActionResult Update(
[FromUri] string serial,
[FromBody] Configuration configuration)
{
}
}
public class ConfigQueryController: ApiController
{
[HttpGet]
[Route("api/device/{serial}/config")]
public IHttpActionResult Get(
[FromUri] string serial)
{
}
}
The reason why i want to have methods for same resource in separate controllers is decoupling queries from commands.
EDIT
To be honest, it's ample code to illustrate my problem, so please don't bother commenting controllers naming ect. It's not important in context of my question.
EDIT 2
I've found here web-api overview thet routing has 3 phases:
Routing has three main phases:
Matching the URI to a route template.
Selecting a controller.
Selecting an action.
So it seems this does not work because controller can't be resolved and method verb (PUT, GET) are not even checked? O_o
Read the error carefully, then look at your attribute routing. You have identical URLs for two different actions.
Program would have no idea which action to execute.
use [FromRoute] instead of [FromUri] annotations

Remove controller name from URL with Attribute routing

I want to remove controller name from URL for specific Controller.
My Controller name is Product
I found some link to do this
Routing with and without controller name
MVC Routing without controller
But all the above links done in route config file. and those are affecting other controller too. I want to do it using Attribute Routing.
Can it is possible? As I want to do this for only Product controller.
I have tried to do it on action like this
[Route("Sample/{Name}")]
but it is not working.
Gabriel's answer is right, however, it can be a bit misleading since you're asking for MVC and that answer is for Web API.
In any case, what you want is to put the annotation over the class definition instead of an action method. MVC example would be like:
[RoutePrefix("SomethingOtherThanProduct")]
public class ProductController : Controller
{
public ActionResult Index()
{
...
return View();
}
}
I'm also dropping this as an answer since you may find the following article helpful: [Attribute] Routing in ASP.NET MVC 5 / WebAPI 2
Make sure you set the RoutePrefix attribute on the whole controller class, as well as using the Route attribute on the action.
[RoutePrefix("notproducts")]
public class ProductsController : ApiController
{
[Route("")]
public IEnumerable<Product> Get() { ... }
}

Different RoutePrefix, same controller name

I'm having a problem with splitting my web-api application into different areas (not mvc areas), using namespaces and RoutePrefix
The application is hosted using Owin Self Host, and in my Startup class I have the following.
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
And my two controllers that I tested with
[RoutePrefix("api/test")]
public class TestController : ApiController
{
[Route("")]
public IHttpActionResult Get()
{
return Ok("api");
}
}
[RoutePrefix("sync/test")]
public class TestController : ApiController
{
[Route("")]
public IHttpActionResult Get()
{
return Ok("sync");
}
}
These two controllers live in two different namespaces, Api and Sync.
When I try to access the two controllers with
http://localhost/api/test and http://localhost/api/sync I get a 404.
But If I rename one of the controllers to e.g. TestApiController then both works.
Someone having a good idea if it's possible to do what I want?
Unfortunately, Web API finds controllers by class name, ignoring the namespace. This is a known issue and is not unique to attribute-based routing.
The easiest work-around by far is to avoid the problem and use unique controller names. But if you don't mind getting a little fancy, here's a solution:
https://blogs.msdn.microsoft.com/webdev/2013/03/07/asp-net-web-api-using-namespaces-to-version-web-apis/

Categories