Reputation: 874
I have searched all the posts on the problem in question, but I have not found any acceptable answer to this problem. I have a controller with Get and Post like this:
[ApiController]
[ApiVersion(StringResources.ApiV10)] //"1.0"
[Route(StringResources.RouteWithVersioning)] //"api/v{version:apiVersion}/[controller]"
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public class ProductsController : ControllerBase
{
private readonly IMediator _mediator;
public ProductsController(IMediator mediator)
{
_mediator = mediator;
}
[HttpPost]
[ProducesResponseType(typeof(CreateProductResponse), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
public ActionResult<CreateProductResponse> Create([FromBody]CreateProductRequest request)
{
try
{
var oid = _mediator.Send(new CreateProdRequest
{
Name = request.Name
});
return CreatedAtRoute(StringResources.GetProduct,
new
{
Oid = oid
},
new CreateProductResponse {Oid= oid});
}
catch (ProductException e) when(e.Errors.Select(err => err.Code).ToList().Contains("DuplicateProductName"))
{
return Conflict(ApiErrors.ProductAlreadyExist4091);
}
}
[HttpGet(Name = StringResources.GetProduct)]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<GetProductResponse> Get([FromQuery]GetProductRequest request)
{
var result = _mediator.Send(new GetRequest
{
Oid = request.Oid
});
if (result == null)
return NotFound();
return Ok(result);
}
}
But when I create a product and return CreateAtRoute
I always get the exception:
exception.System.InvalidOperationException: No route matches the supplied values.
The class GetProductRequest
contains only Oid
properties.
I tried to use CreateAtAction
too but the URI returned in the header is wrong (it doesn't contain the path /api/v1/Products
).
The startup configuration for middleware
is this:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
And for services is:
services.AddApiVersioning(options =>
{
options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
});
services.AddVersionedApiExplorer(options =>
{
options.GroupNameFormat = "'v'VVV";
options.SubstituteApiVersionInUrl = true;
});
I believe that the problem is due to the fact that the API versioning is present in the path, but I don't know how to fix it.
Upvotes: 3
Views: 885
Reputation: 4614
The route ("api/v{version:apiVersion}/[controller]"
) needs a parameter named version
, so pass the ApiVersion
in to your action and send it along with the route values:
public ActionResult<CreateProductResponse> Create(
[FromBody] CreateProductRequest request,
ApiVersion version) // <-- Add this
{
⋮
return CreatedAtRoute(
StringResources.GetProduct,
new
{
Oid = oid,
version = version.ToString() // <-- And this
},
new CreateProductResponse {Oid = oid});
}
Upvotes: 5