ASP.NET Core routing error - asp.net-core

I have a route like http://localhost:63037/api/futuresMarginRuns/7/data which is working however another controller API with route http://localhost:63037/api/futuresMarginRuns/2018-07-11/data is not working, even the breakpoint in the controller API is not hit.
Here are the API signatures
[HttpGet]
[Route("/api/futuresMarginRuns/{id}/data")]
public async Task<IActionResult> GetFuturesMarginRunDataAsync(long id)
{
var data = await _repository.GetAllAsync(id).ConfigureAwait(false);
return Ok(data);
}
[HttpGet]
[Route("/api/futuresMarginRuns/{runDate}/data")]
public async Task<IActionResult> GetFuturesMarginRunDataByDateAsync(DateTime runDate)
{
var data = await _repository.GetAllAsync(runDate).ConfigureAwait(false);
return Ok(data);
}
In the first case I get json data but in the second one the breakpoint is not hit so looks like the route is not mapped to the API properly in which case I would expect an error, but i get empty []
How can I the API to work?
Thanks

You need to add some route constraints to your routes. Route constraints tell the routing engine that if id is supposed to be an int, only match that route if the text in that spot can be converted to an int (and similarly with dates, etc).
So I would change your routes to the following:
[HttpGet]
[Route("/api/futuresMarginRuns/{id:long}/data")]
public async Task<IActionResult> GetFuturesMarginRunDataAsync(long id)
[HttpGet]
[Route("/api/futuresMarginRuns/{runDate:datetime}/data")]
public async Task<IActionResult> GetFuturesMarginRunDataByDateAsync(DateTime runDate)

Related

How can I add links to other controller methods in generated OpenAPI specs using attributes in ASP.NET Core?

I am using SwaggerGen to generate an OpenAPI spec for our API, and would like to add links between certain endpoints.
OpenAPI 3.0 Links
Is there a way to add an attribute to the controller method that links to another controller method?
For example, if I currently have something like
[HttpPost]
[Route("~/users")]
[ProducesResponseType(typeof(ResponseObject<UserId>), StatusCodes.Status200OK)]
public async Task<IActionResult> CreateUser(...)
{
// Create user
}
[HttpGet]
[Route("~/users/{userId}")]
[ProducesResponseType(typeof(ResponseObject<User>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetUser(...)
{
// Get newly created user
}
Could I somehow link them like
[HttpPost]
[Route("~/users")]
[ProducesResponseType(typeof(ResponseObject<UserId>), StatusCodes.Status200OK)]
[Link(nameof(GetUser), "UserId")]
public async Task<IActionResult> CreateUser(...)
{
// Create user
}
[HttpGet]
[Route("~/users/{userId}")]
[ProducesResponseType(typeof(ResponseObject<User>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetUser(...)
{
// Get newly created user
}
to generate the "links" field as shown in the OpenAPI 3.0 spec linked above?

How to remove value from route int .net core

I'm writing .net core mvc app. I have two methods
[HttpGet("{action}/{userId}")]
public async Task<IActionResult> ChangeUser(string userId)
{
var user = await _dbContext.Users.Where(x => x.Id == userId).FirstOrDefaultAsync();
...
return View(new ChangeUserVM());
}
[HttpPost("{action}/{userId}")]
public async Task<IActionResult> ChangeUser(ChangeUserVM user)
{
...
}
I need routing in the HttpGet method to get into the first method. But then i want to get from the html to the second method and i have to use routing again otherwise i get 405. How i can get rid of routing in the second method?
I can’t verify my suggestion right now, but over second method, try to remove from HttpPost attribute “userId”.
[HttpPost(“action”)]
public async Task<IActionResult> ChangeUser(ChangeUserVM user)

In asp.net API HttpGet{id} works but when I change the {id} to something else it dose not work

Im pretty new to ASP core webAPI. Hopefully you guys can give me a hand.
I have been successfully using HttpGet{id} - postman has been serving the correct information back. However, I want to be able use "partNumber" in the url.
below is the working id get method:
'''
[HttpGet("{id}")]
public async Task<ActionResult<Model>> GetModel(int id)
{
return await _context.Models.FindAsync(id);
}
'''
Here is the actual parameters that I would like to search on:
```
[HttpGet("{PartNumber}")]
public async Task<ActionResult<Model>> GetModel(int partNumber)
{
return await _context.Models.FindAsync(partNumber);
}
```
Postman returns 404 not found in the latter when I should see data returned.
Any help would be greatly appreciated.
thanks
404 means the request url is not correct.
Here is my whole backend code and my controller contains [Route("api/[controller]")] attribute:
[Route("api/[controller]")]
[ApiController]
public class TestsController : ControllerBase
{
[HttpGet("{partNumber}")]
public async Task<ActionResult<Model>> GetModel(int partNumber)
{
}
}
The request url should be:https://localhost:44371/api/tests/YourPortNumber(https://localhost:44371/api/tests/1).
Result:
For NoContent return in postman,please set breakpoint and check if database contain such record with the specific partNumber:
[HttpGet("{partNumber}")]
public async Task<ActionResult<Model>> GetModel(int partNumber)
{
//set breakpoint here...
var data = await _context.Models.FindAsync(partNumber);
return await _context.Models.FindAsync(partNumber);
}
Result:
[HttpGet("{partNumber}")]
public async Task<ActionResult<Model>> GetModel(int partNumber)
{
return await _context.Models.FindAsync(partNumber);
}
The casing of the string in the route should match the parameter

Unable to configure route for Get in WebApi 2

I'm struggling with something very basic. I'm trying to be get a response from my WebApi2 restful service, and I can't.
I have not edited the default WebApi (WebApiConfig.cs) route.
This is the controller
public class AboutController
{
[Route("api/about/{id:int}/{service1}/{service2}")]
public async Task<IHttpActionResult> Get(int accountId, string mainservice, string secondaryservice)
{
//logic
}
}
If I navigate (in a browser) to http://localhost:58090/api/about I get the error message The requested resource does not support http method 'GET'. I guess this makes sense, as it doesn't match the route (path).
If I update the path to something which matches the signature, such as http://localhost:58090/api/about/1/a/b I get the error message No action was found on the controller About' that matches the request.
Even if I add [HttpGet] to the controller, it makes no difference.
As a sanity test, I updated to
public class AboutController
{
public async Task<IHttpActionResult> Get()
{
//logic
}
}
and it does what is expected. I'm lost as to why adding the parameters has confused things so much.
I'm lost as to what I've done wrong
The route must match the parameters
[Route("api/about/{id:int}/{service1}/{service2}")]
public async Task<IHttpActionResult> Get(int id, string mainService, string secondaryService)
{
The above won't work, because it is expecting to see service1 and service2 based upon the route.
Update as per the example below
[Route("api/about/{id:int}/{service1}/{service2}")]
public async Task<IHttpActionResult> Get(int id, string service1, string service2)
{

How to Get Route Data from Middleware for ASPNETCORE OData request?

I have the following Middleware class which gets the route data for the current request.
If you perform a Get on the Values Controller you will see the context.GetRouteData() returns a value and is not null. I have wired Swagger\Swashbuckle into the attached project to make this easier to demo.
However, if you call the Blog OData controller (http://localhost:40946/odata/Blog), context.GetRouteData() returns null.
Does anyone know how to access the RouteData from middleware for an OData request?
public class TestMiddleware
{
protected readonly RequestDelegate _next;
public TestMiddleware(RequestDelegate next)
{
this._next = next;
}
public virtual async Task Invoke(HttpContext context)
{
var routeData = context.GetRouteData();
await this._next.Invoke(context);
}
}
Link to sample solution demonstrating the issue.
Looks like the OData Middleware isn't providing the routing info as a IRoutingFeature to the context. Link to Source Code
Not sure the root cause - but as a workaround you could use
var httpRequestFeature = context.Features[typeof(IHttpRequestFeature)] as IHttpRequestFeature;
var path = httpRequestFeature?.Path;