Laden...

WebAPI POST CreatedAtAction Fehlermeldung

Erstellt von lhyn vor 2 Jahren Letzter Beitrag vor 2 Jahren 532 Views
L
lhyn Themenstarter:in
136 Beiträge seit 2015
vor 2 Jahren
WebAPI POST CreatedAtAction Fehlermeldung

Hallo zusammen,

Ich habe ein Problem mit meiner WebAPI, welche ich "modernisieren" möchte und finde den Fehler nicht.
Beim Aufruf der folgenden Methode wird bei CreatedAtAction ein Fehler im Swagger ausgegeben.


        // POST /api/Project
        [HttpPost]
        public async Task<ActionResult<ProjectDto>> CreateProjectAsync([FromBody] CreateProjectDto projectDto)
        {
            var existingId = await repository.GetProjectByIdAsync(projectDto.Id);
            if(existingId is null)
            {
                ProjectModel project = new()
                {
                    Uid = projectDto.Uid
                };
                // Projekt wird dem InMemProjectRepository korrekt hinzugefügt
                await repository.CreateProjectAsync(project);

                // Hier, bei der CreatedAtAction tritt der Fehler auf
                return CreatedAtAction(nameof(GetProjectByIdAsync), new { id = project.Id }, project.AsDto());
            }
            else if(existingId.Id == projectDto.Id)
            {
                return BadRequest();
            }

            return BadRequest();
        }


       // GET /api/Project/{id}
        [HttpGet("{id}")]
        public async Task<ActionResult<ProjectDto>> GetProjectByIdAsync(int id)
        {
            var project = await repository.GetProjectByIdAsync(id);

            if (project is null)
            {
                return NotFound();
            }

            return project.AsDto();
        }

Fehlermeldung:
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.InvokeNextResultFilterAsyncTFilter,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 Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS
=======
Content-Type: application/json
:authority: localhost:5001
:method: POST
:path: /api/Project
😒cheme: https
Accept: text/plain
Accept-Encoding: gzip, deflate, br
Accept-Language: de-CH,de-DE;q=0.9,de;q=0.8,en-US;q=0.7,en;q=0.6
Cookie: ai_user=nITrk|2022-01-04T22:21:05.590Z,ai_session=TVQAp|1641372830052|1641372830052
Host: localhost:5001
Referer: https://localhost:5001/swagger/index.html
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
Origin: https://localhost:5001
Content-Length: 72
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
sec-fetch-site: same-origin
sec-fetch-mode: cors
sec-fetch-dest: empty

Ich danke Euch für die Unterstützung.

Gruss Lhyn

T
2.219 Beiträge seit 2008
vor 2 Jahren

Müsste im Header bei Accept nicht auch application/json stehen?
Dort ist aktuell text/plain eingetragen.
Ansonsten sieht es auf den ersten Blick korrekt aus.
Hast du auch die Default Route gesetzt bzw. wie sehen die Routing Einstellungen aus?

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

L
lhyn Themenstarter:in
136 Beiträge seit 2015
vor 2 Jahren

Hallo T-Virus,

Danke Dir für die schnelle Antwort.

Routing:


    [ApiController]
    [Route("api/[controller]")]     // api/Project

Muss mich mal schlau machen, wie ich produces = application/json einstellen kann.
Habe ich auf die schnelle nicht herausgefunden...

Gruss Lhyn

C
55 Beiträge seit 2020
vor 2 Jahren

Hallo,

Produces ist wie HttpGet und HttpPost ein Attribut mit einem entsprechenden Parameter.


[Produces("application/json")]

Grüße

16.807 Beiträge seit 2008
vor 2 Jahren

Verwende immer Routes und keine Action-Links.
Und generier Deine Links mit Hilfe des LinkGenerator

Routes sind viel performanter (im Vergleich), viel einfacher zu pflegen und zu verlinken.
Hinzu kommt dass Routes die einzigen Definitionen sind, die früh beim App Start knallen - alle andere erst beim Call.
Dadurch immer schwer zu testen.

L
lhyn Themenstarter:in
136 Beiträge seit 2015
vor 2 Jahren

Hallo zusammen,

Habe es nun mit [Produces("application/json")] getestet und Accept ist nun im Json-Format, danke dafür.
CreatedAtAction knallt aber leider noch immer.

Bin kurz davor es mit einem return Ok(project.AsDto()); zu basteln 😉

@Abt, kannst Du bitte genauer auf Deine Lösung für mein Beispiel eingehen?
Habe mir vorhin die Doku angeschaut und nach Umsetzungen gegoogelt, leider ohne Erfolg
Scheint als arbeiten noch nicht viele mit dem LinkGenerator für Routing

Gruss Lhyn

16.807 Beiträge seit 2008
vor 2 Jahren

Weiß nicht nach was Du gegoogelt hast, aber dann wohl nicht richtig Google Suche nach "c# linkgenerator sample"
https://wildermuth.com/2018/10/15/LinkGenerator-in-ASP-NET-Core-2-2/
Den Link Generator gibs schon paar Jahre.

Ansonsten ASP Core Routing Basics
Routing in ASP.NET Core

Code:

  • Du verwendest das Routing Tag für den Pattern und den Name
  • Die Url erzeugst Du dann anhand des Names und der Parameter via LinkGenerator

Hier der ca. 5 Jahre alte Link von Marius
Generating Route URLs in ASP.NET Core MVC — Marius Schulz

Ansonsten sieht man eigentlich auch schon an den Parametern alleine, was man übergeben kann.
Sind ja nur eine Handvoll Möglichkeiten.

L
lhyn Themenstarter:in
136 Beiträge seit 2015
vor 2 Jahren

Danke Dir, dachte das muss doch etwas neues sein...
Werde ich mir anschauen und gegebenenfalls umsetzen.

Gruss Lhyn