I have an API to convert currencies based on a local database. I create my controller, serive, repository and even though I can perform the query in the database I don't get the same result via API.I've already spent a few hours trying to solve this and nothing seems to work, here's the print.enter image description here. This case not is equals my problem because my swagger loads. This case not is equal my problem because i don't care about swagger color.
My controller:
[ApiController]
[Route("api/[Controller]")]
public class CurrencyController : ControllerBase
{
[HttpGet]
[Route("{code}")]
public ObjectResult GetByCode([FromServices] CurrencyReadRepository repository, string code)
{
return Ok(repository.GetCurrency(code));
}
...
You can try on StartUp.cs:
services.AddTransient<CurrencyReadRepository>();
Related
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.
I am working on an API.
I have an "AbstractController.cs" and I am having difficulties calling a GET with two parameters.
[Route("api/[controller]")]
[ApiController]
public class AbstractController : ControllerBase
{
// GET: api/Abstract
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "missing implementation" };
}
Going to https://localhost:44363/api/abstract/ generates this.
["missing implementation"]
Awesome!
Now I need to make the Get method that passes in a show year, and code to a SQL query. Easy enough?
// GET: api/Abstract?ShowYear=2019&ShowCode=248621
[Route("api/{controller}/{ShowYear}/{ShowCode}")]
[HttpGet]
public Abstract Get(int ShowYear, int ShowCode) // GetAbstractByYearAndSHCode
{
string x = "";
return new Abstract();
}
No matter what I do I can't get this method to breakpoint/enter execution!
I'm guessing it's a routing issue, but I've tried most tenable ways of calling the endpoint.
Now I check the MS Documentation like any self-respecting-learning-programmer would.
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-3.1
Endpoint routing in ASP.NET Core 3.0 and later:
Doesn't have a concept of routes. Doesn't provide ordering guarantees
for the execution of extensibility, all endpoints are processed at
once.
GULP Sounds scary.
I haven't touched my middleware at this point.
All examples I've looked at don't have my "MapControllers();" method in their Startup.cs.
This is because it's new to .NET Core 3.0/3.1
The method: "Adds endpoints for controller actions to the IEndpointRouteBuilder without specifying any routes."
OK, so do I have to manually specify the route here still?
I did this, and it sorta works.
Well, it breakpoints in the startup.cs now when I go to https://localhost:44363/api/abstract/2019/287
Wait, it's not doing ANYTHING with my controller code! Why?
The following (also above) code ends up declaring as a null in the startup.cs
var controller = context.Request.RouteValues["Abstract"];
Hoping to learn what I'm doing wrong.
MapGet("/api/abstract/{showYear}/{showCode}", ...);
Isn't this code responsible for mapping that route with the controller named AbstractController.cs in my Controllers folder? Not hitting any breakpoints.
Edit:
Reading through this which compares the differences in the Startup.cs from .Net Core 2, 2.2, MVC projects vs 3.0
I have a good feeling reading all of this, I will find the issue.
https://andrewlock.net/comparing-startup-between-the-asp-net-core-3-templates/
Edit.. nevermind didn't find a resolution.
Edit 2:
Completely commenting out this troublesome code in startup.cs:
endpoints.MapGet("/api/abstract/{showYear}/{showCode}", async context =>
{
var controller = context.Request.RouteValues["Abstract"];
var showYear = context.Request.RouteValues["showYear"];
var showCode = context.Request.RouteValues["showCode"]; // just an example.
//await context.Response.WriteAsync($"Hello {showYear} is your year, {showCode} for the code!");
//GetAbstractByYearAndSHCode();
});
endpoints.MapGet("/api/abstract/{showYear}", async context =>
{
var name = context.Request.RouteValues["name"];
await context.Response.WriteAsync($"Hello {name}!");
});
Resolves my issue of not being able to reach the controller.
https://localhost:44363/api/abstract/2019 hits, and the id value is 2019. Great.
https://i.imgur.com/rmHyDPg.png the output looks great.
I am still not able to use > 1 parameter. How do I simply use the Year, and ShowCode paramaters? What's the syntax?
https://localhost:44363/api/abstract/2019
Just add the parameters to your attribute
[HttpGet("{ShowYear}/{ShowCode}")]
The "api/abstract" route is already used by the first method.
You cannot use it again for other actions. Create a new one as shown inline.
[HttpGet("{GetAbstractByYearAndSHCode}",Name = "GetAbstractByYearAndSHCode")]
public Abstract Get(int ShowYear, int ShowCode) // GetAbstractByYearAndSHCode
{
string x = "";
return new Abstract();
}
And call the url as shown:
https://localhost/api/abstract/GetAbstractByYearAndSHCode?ShowYear=1&ShowCode=5
I am creating a c# .net core 2.2 web API for my next project. My question is when returning data should I return the object or IActionResult OK(returnObject)?
The reason I ask is I am using swagger and swagger studio to create my models for an Angular front end. If I return an IActionResult from the API the returned view models are not detailed in the swagger.json file so I would have to code these in the angular application. If I return whatever object is created the model is created in the swagger.json.
What practice should I follow to return data from an API in this case?
You do want to return IActionResult(object) but you are not quite done.
Annotate your controller with the ProducesAttribute and annotate your method with the ProducesResponseTypeAttribute:
[Produces("application/json")]
public class SomethingController
{
[ProducesResponseType(typeof(YourObject), (int)HttpStatusCode.OK)]
public IActionResult GetThing(int id)
{ ... }
}
This allows Swagger UI to know what to expect and document it appropriately. Shown above is for a synchronous method; it works for asynchronous as well.
You can return
- Specific Type
- IActionResult
- ActionResult
For more details, please refer MSDN article at : https://learn.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-2.2
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() { ... }
}
I'm currently trying out the new ApiController available with WebAPI - namely the POST method as I'm having no luck with binding the properties for the model.
This is my code for the ApiController:
public class GameController : ApiController
{
public void Post([FromBody]GameVMTest gameVM)
{
}
}
In this example, I'm able to make a HTTP Post to this method. The GameVM property is initialised but none of the properties bind.
So I thought this might be caused by my method of HTTP Post and so I wrote another Post method but this time, using just a class that inherits a Controller class:
public class TestController : Controller
{
[HttpPost]
public void Post(GameVMTest gameVM)
{
}
}
I used the same HTTP Post to this TestController Post method and everything works just fine.
Any idea on why the property binding works for a class inheriting the Controller class but not the ApiController class?
Note: I have tried removing the [FromBody] attribute and this does nothing.
Note: GameVM property contains simple String & Int variables - nothing complex.
Thanks in advance.
Note:
The http post call is from an iOS app using Alamofire.
Below is the JSON String passed to the two methods above:
"{\"isDirty\":1,\"courtName\":\"Court 1\",\"id\":11418,\"team1\":\"Kenja Hurricane\",\"team2\":\"Sons of Asia\",\"roundId\":528}"
After reading this
https://lbadri.wordpress.com/2014/11/23/web-api-model-binding-in-asp-net-mvc-6-asp-net-5/
Turns out the body of the request has to be very specific for WebAPI!!!