Even though it looks like a duplicate question, none of the StackOverflow answers seem to fit or solve my problem.
Basically, I'm making a REST API using ASP.NET 5, with two entities: "Server" and "Video", the entity "Video" being dependent on the entity "Server".
The GET, POST, PUT, DELETE... methods are all working with the "Server" entity; the problem is when I try to use POST on the "Video" entity.
System.InvalidOperationException: No route matches the supplied values.
at Microsoft.AspNetCore.Mvc.CreatedAtActionResult.OnFormatting(ActionContext context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsyncCore(ActionContext context, ObjectResult result, Type objectType, Object value)
at Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsync(ActionContext context, ObjectResult result)
at Microsoft.AspNetCore.Mvc.ObjectResult.ExecuteResultAsync(ActionContext context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultAsync(IActionResult result)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextResultFilterAsync[TFilter,TFilterAsync]()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
The funny part is that, even though it returns the error, the JSON is being posted successfully when I check with GET.
Here's a chunk of VideosController's code:
namespace SeventhApi.Controllers
{
[Route("api/servers/{serverId}/videos")]
[ApiController]
public class VideosController : ControllerBase
{
private readonly VideoContext _context;
public VideosController(VideoContext context)
{
_context = context;
}
[HttpGet("{id}")]
public async Task<ActionResult<Video>> GetVideo(Guid id)
{
var video = await _context.Videos.FindAsync(id);
if (video == null)
{
return NotFound();
}
return video;
}
[HttpPost]
public async Task<ActionResult<Video>> PostVideo(Video video)
{
_context.Videos.Add(video);
await _context.SaveChangesAsync();
return CreatedAtAction("GetVideo", new { id = video.VideoId }, video);
}
And a chunk o the Startup:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDbContext<ServerContext>(opt => opt.UseInMemoryDatabase("Server"));
services.AddDbContext<VideoContext>(opt => opt.UseInMemoryDatabase("Video"));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
From the answers I've found here, I'm inclined to think it's some routing error, but none of the answers have solved my problem.
CodePudding user response:
url have two parameters, {serverId} {id}.
return CreatedAtAction("GetVideo", new { id = video.VideoId, serverId = 1 }, video);
CodePudding user response:
As Hazrelle replied, it was really a matter of using nameof(GetVideo):
[HttpPost]
[ActionName(nameof(GetVideo))]
public async Task<ActionResult<Video>> PostVideo(Video video)
{
_context.Videos.Add(video);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetVideo), new { id = video.VideoId }, video);
}