0

Overview
-Blazor Server project using REST API.
-HttpClient calls my API using PostJsonAsync<>
-Db is updated successfully and returns expected JSON
-API Controller Try/Catch does not throw exception, executes return CreatedAtAction()
-Output shows API returns 500: Internal Server Error
-When executing POST using Swagger, same line is executed and returns 201

I'm at a loss for what is going wrong. I've only been coding since July, so I'm hoping it's just my lack of experience that's blinding me to the obvious problem in my code. This is the offending method:

        public async Task<ActionResult<PlayerCharacter>> CreatePlayerCharacter(PlayerCharacter playerCharacter)
        {

            try
            {
                if (playerCharacter != null)
                {
                    var newPlayerCharacter = await _playerCharacterRepository.AddPlayerCharacter(playerCharacter);

                    //This is the last line of code to execute before the web app crashes with Status Code 500. Executes fine and returns 201 from Swagger.
                    return CreatedAtAction(nameof(GetPlayerCharacter), new { id = newPlayerCharacter.Id }, newPlayerCharacter);
                }

                return BadRequest();
            }
            catch (Exception e)
            {
                //This break point is not reached
                Console.WriteLine(e.StackTrace);
                return StatusCode(StatusCodes.Status500InternalServerError, "Error posting data to the database.");
            }
        }

GitHub Repo

Trevor
  • 43
  • 6
  • 1
    Remove the try/catch altogether (because ASP.NET Core has built-in exception handling for this), and then look at your server’s logs to see what is going on. The exception message should give you a good idea there. – poke Jan 24 '21 at 17:12
  • That's good to know, thank you! I removed the try/catch and found that the same message is displayed in my stack trace. – Trevor Jan 24 '21 at 17:29
  • 1
    You’re looking at the stack trace of the consumer though; it only receives the 500 error. Check out your server logs for details what caused the error 500. – poke Jan 24 '21 at 17:31
  • I fear this is where my lack of experience comes in...I'm not sure how to do that. I've attached SQL Server Management Studio to my LocalDb and I can see the Db there. I have also located an LDF for the db. The internet seems to think that understanding that requires quite an in-depth understanding of T-SQL, which I do not yet possess. Can you recommend a resource to guide me through finding these logs? – Trevor Jan 24 '21 at 17:46
  • 1
    You will need to look at the ASP.NET Core logs. If you are launching your app from within Visual Studio using IIS Express, then check the “Output” panel and select “ASP.NET Core” from the drop down there. Otherwise, if you are launching the app as a console app (or from elsewhere than VS), then you should have a console window open somewhere which should contain all the logs. – poke Jan 24 '21 at 17:52
  • Ah! I have learned something new! It appears the exception is: System.Text.Json.JsonException: A possible object cycle was detected...[et al]. It appears that I need to put in a reference loop handler. This information looks like it's old and it doesn't quite work. I have to run an errand, but I will research this more later. Thank you so much for your help! https://entityframeworkcore.com/knowledge-base/59199593/-net-core-3-0-possible-object-cycle-was-detected-which-is-not-supported – Trevor Jan 24 '21 at 18:11

1 Answers1

0

The root cause of the problem is as yet not fully understood, but I do know how I fixed it.

After poke taught me how to look at the ASP.NET Core logs, I discovered this exception:
System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles.

Researching that lead me to several resources:

The solution may be that I should refactor my code to use DTOs (something I'll have to read up on because I don't understand that yet). In the meantime, the bandaid that will allow me to proceed is:

  1. Install NuGet Package Microsoft.AspNetCore.Mvc.NewtonsoftJson
  2. In Statup.cs in ConfigureServices add
services.AddControllers().AddNewtonsoftJson(options =>
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);

Thank you to everyone who helped me think through this. I greatly appreciate your assistance!

Trevor
  • 43
  • 6
  • 1
    The error likely happens because you are returning `newPlayerCharacter` which is of type `PlayerCharacter` which has references to things like `PlayerAttribute` which again link back to the `PlayerCharacter`. When serializing this as JSON, the serializer will just follow these object paths down to infinity (until it breaks). – The better practice is to define a custom data transfer object (DTO) which you return that is well-serializable. That way, you also make it easier to hide certain implementation details the client shouldn’t know or doesn’t need to know. – poke Jan 25 '21 at 11:19