Tarkacode
Tarkacode
CC#
Created by Tarkacode on 3/5/2024 in #help
✅ My API returns 500 internal server error with the SQL exception text, why?
Hello every one, I built an ASP.NET API in .NET and I wrote a controller Action that looks like this :
[HttpPost]
public async Task<ActionResult<RecipeIngredientDto>> Post(RecipeIngredientRequest recipeIngredientRequest)
{
try
{
RecipeIngredient recipeIngredient = recipeIngredientRequest.MapToRecipeIngredient();

await _recipeIngredientRepository.Create(recipeIngredient);

RecipeIngredientDto dto = recipeIngredient.MapToDto();
return Ok(dto);
// TODO: Return CreatedAtAction when Get action is made
}
catch (ArgumentOutOfRangeException ex)
{
return BadRequest(ex.Message);
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
[HttpPost]
public async Task<ActionResult<RecipeIngredientDto>> Post(RecipeIngredientRequest recipeIngredientRequest)
{
try
{
RecipeIngredient recipeIngredient = recipeIngredientRequest.MapToRecipeIngredient();

await _recipeIngredientRepository.Create(recipeIngredient);

RecipeIngredientDto dto = recipeIngredient.MapToDto();
return Ok(dto);
// TODO: Return CreatedAtAction when Get action is made
}
catch (ArgumentOutOfRangeException ex)
{
return BadRequest(ex.Message);
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
So, as you can see, I return as a response to the HTTP caller either an "Ok" response, or a "BadRequest" response. If I try a request that is not supposed to work yet, using Postman, the server can't handle my request... so, that is completely correct. But what I don't understand is that my API returns a 500 internal server error response with the whole SQL Exception text as a response to my postman client. I think it is a bad idea to show the whole SQL Exception text message to the client. I could understand why. But why does my API even give this 500 response? I never wrote a 500 response in my controller action. What am I supposed to do to "hide" the Exception text messages? Do I need to write a custom text and return a 500 response manually with this text for every action of every controller, like in a more generic catch (Exception ex) ? What could be considered as best practice in this case? Thank you for reading this, and many thanks for any reply! 😁
7 replies
CC#
Created by Tarkacode on 2/9/2024 in #help
✅ How to properly set a default value as UtcNow with EF Core and PostgreSQL
Hi there, I use EF Core with a PostgreSQL DB. I want that each time I add an entity with EF Core in the DB, it saves the CreatedOn field with the value of the UtcNow. I tried this :
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Ingredient>().Property(i => i.CreatedOn).HasDefaultValue(DateTime.UtcNow);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Ingredient>().Property(i => i.CreatedOn).HasDefaultValue(DateTime.UtcNow);
}
But when I do "Add-Migration", I see that EF Core just saves the UtcNow once and will give this same value for every entity that I add. If its 14h when I do the migration, every entity that I will add in the future will have this 14h value in the CreatedOn. It is not dynamic. And the NOW() PostgreSQL function like this doesn't give the UtcNow unfortunately :
modelBuilder.Entity<Ingredient>().Property(i => i.CreatedOn).HasDefaultValueSql("NOW()");
modelBuilder.Entity<Ingredient>().Property(i => i.CreatedOn).HasDefaultValueSql("NOW()");
What are my options to do what I want to do? I saw that I can write this property code in my EF Core Entity model
public DateTime CreatedOn { get; set; } = DateTime.UtcNow;
public DateTime CreatedOn { get; set; } = DateTime.UtcNow;
Can it work? And also, is it a good practice? Or should I use the Entity model constructor, something like :
public class Ingredient
{
public Ingredient()
{
CreatedOn = DateTime.UtcNow;
}
}
public class Ingredient
{
public Ingredient()
{
CreatedOn = DateTime.UtcNow;
}
}
What do you think? I will very much appreciate every reply 🥳
9 replies
CC#
Created by Tarkacode on 12/30/2023 in #help
String : Immutable reference type
Hello! I don't understand something in C#, and I would love to have some guidance. In the following code, the variable storing the string called "status" still has the value "Healthy" when outside the method scope.
string status = "Healthy";

Console.WriteLine($"Start: {status}");
SetHealth(status, false);
Console.WriteLine($"End: {status}");

void SetHealth(string status, bool isHealthy)
{
status = (isHealthy ? "Healthy" : "Unhealthy");
Console.WriteLine($"Middle: {status}");
}
string status = "Healthy";

Console.WriteLine($"Start: {status}");
SetHealth(status, false);
Console.WriteLine($"End: {status}");

void SetHealth(string status, bool isHealthy)
{
status = (isHealthy ? "Healthy" : "Unhealthy");
Console.WriteLine($"Middle: {status}");
}
Prints :
Start: Healthy
Middle: Unhealthy
End: Healthy
Start: Healthy
Middle: Unhealthy
End: Healthy
And I would love to understand why. If the string status is passed as a reference type in the method "SetHeatlh", it means that "status" called in the method as an argument, is a variable with the address of the string "Healthy" somewhere in the Heap. When the method says
status = (isHealthy ? "Healthy" : "Unhealthy");
status = (isHealthy ? "Healthy" : "Unhealthy");
Should it not mean that a new string with value "Unhealthy" is created on the Heap, and then the variable "status" should store the new address of this new string object in itself as a variable? Why is the address of the status not changed when we go out of the method SetHealth? I thought any change on an reference type variable inside a method should be saved outside of this method? Any help gladly appreciated 👍
37 replies
CC#
Created by Tarkacode on 10/4/2023 in #help
✅ Auth0 and ASP.NET API
No description
40 replies
CC#
Created by Tarkacode on 9/24/2023 in #help
✅ AuthorizationHandlerContext in ASP.NET API with Auth0
Hello 😅 I am trying to implement Auth0 in my ASP.NET API consumed by Angular app. It is a personal project. For some reason that i can't find, I am not authorized to Update my Ingredient (Its an application to manage cooking recipes). I tried to follow every guides from Auth0 to implement it right, and i really can't find where i did wrong. Right now, if i call the API endpoint to update ingredient, it says I am Unauthorized (in the logs): 2023-09-24 02:40:18.414 +02:00 [INF] Authorization failed. These requirements were not met: Kitchen.Api.Tools.HasScopeRequirement When i debug my API, and i arrive at the point of this code :
public class HasScopeHandler : AuthorizationHandler<HasScopeRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasScopeRequirement requirement)
{
// If user does not have the scope claim, get out of here
if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer))
return Task.CompletedTask;
...
public class HasScopeHandler : AuthorizationHandler<HasScopeRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasScopeRequirement requirement)
{
// If user does not have the scope claim, get out of here
if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer))
return Task.CompletedTask;
...
I see that my "context" has an error in Resource. It says in the debug window : Session = '((Microsoft.AspNetCore.Http.DefaultHttpContext)context.Resource).Session' threw an exception of type 'System.InvalidOperationException' Also this context has no claims, that's why it returns out of the method and says I am Unauthorized... I guess ? I am trying to make a good auth for my app and i have no idea of where to look at to solve this problem. Thank you for reading this, i hope someone will be able to give me some direction. Peace ✌️
164 replies
CC#
Created by Tarkacode on 9/18/2023 in #help
❔ Which auth provider for ASP.API + Angular?
Hello 👋 I would like to set up an authentication and authorization system for my personal project, which uses an ASP.API and an Angular client. I'm a junior, and I've always cobbled together an auth system. I'd like to do something credible this time (but free). But I'm a bit desperate because I can't find a recent tutorial for my stack. I've heard of OAuth2 with OpenId Connect, Duende Identity Server as an authentication provider and PKCE protocol but the tutorial I found uses ASP MVC and not Angular 😢 and the man who made the tutorial says that securing ASP.MVC and Angular apps are two really different things... My question is: what credible auth could I start with ASP.API + Angular? And would you have a tutorial to recommend? Thank you for reading my message. And sorry if I give the impression of not doing any research myself. The reality is that I've been struggling to get back into coding for several weeks now, and it seems like a very hard task at the moment.
10 replies
CC#
Created by Tarkacode on 7/29/2023 in #help
Test ASP.API controller with xUnit: can't assert Type
Hello 👋 I hope my question is not too dumb but I m stuck on the testing of my API controller. (It is my first test project) Me controller looks exactly like this :
[HttpGet]
public async Task<ActionResult<IEnumerable<RecipeDto>>> GetRecipes(
[FromQuery] int pageNumber,
[FromQuery] int pageSize,
[FromQuery] string? title,
[FromQuery] string? searchQuery)
{
try
{
(IEnumerable<Recipe> recipes, PaginationMetadata metadata) = await _recipeService.GetPage(pageNumber, pageSize, title, searchQuery);

if (recipes is null || recipes.Any() == false)
{
_logger.LogInformationGetAll(nameof(Recipe));
return NotFound();
}

IEnumerable<RecipeDto> response = recipes.Select(r => r.MapToRecipeDto());

Response.Headers.Add("X-Pagination", JsonSerializer.Serialize(metadata));
return Ok(response);
}
catch (Exception ex)
{
_logger.LogCriticalGetAll(nameof(Recipe), ex);
return this.InternalErrorCustom();
}
}
[HttpGet]
public async Task<ActionResult<IEnumerable<RecipeDto>>> GetRecipes(
[FromQuery] int pageNumber,
[FromQuery] int pageSize,
[FromQuery] string? title,
[FromQuery] string? searchQuery)
{
try
{
(IEnumerable<Recipe> recipes, PaginationMetadata metadata) = await _recipeService.GetPage(pageNumber, pageSize, title, searchQuery);

if (recipes is null || recipes.Any() == false)
{
_logger.LogInformationGetAll(nameof(Recipe));
return NotFound();
}

IEnumerable<RecipeDto> response = recipes.Select(r => r.MapToRecipeDto());

Response.Headers.Add("X-Pagination", JsonSerializer.Serialize(metadata));
return Ok(response);
}
catch (Exception ex)
{
_logger.LogCriticalGetAll(nameof(Recipe), ex);
return this.InternalErrorCustom();
}
}
And i am trying to test the first case : Recipes.Any() = false, in this test :
[Fact]
public async Task GetRecipes_Empty_ReturnsNotFound()
{

// Arrange
Tools.RecipeService recipeService = new Tools.RecipeService();
RecipesController controller = new RecipesController(new NullLogger<RecipesController>(), recipeService);

// Act
ActionResult<IEnumerable<RecipeDto>> result = await controller.GetRecipes(1, 5, null, null);

// Assert
Assert.NotNull(result);
Assert.IsType<ActionResult<IEnumerable<RecipeDto>>>(result);
Assert.IsType<NotFoundResult>(result);
Assert.Equal(controller.NotFound(), result);
}
[Fact]
public async Task GetRecipes_Empty_ReturnsNotFound()
{

// Arrange
Tools.RecipeService recipeService = new Tools.RecipeService();
RecipesController controller = new RecipesController(new NullLogger<RecipesController>(), recipeService);

// Act
ActionResult<IEnumerable<RecipeDto>> result = await controller.GetRecipes(1, 5, null, null);

// Assert
Assert.NotNull(result);
Assert.IsType<ActionResult<IEnumerable<RecipeDto>>>(result);
Assert.IsType<NotFoundResult>(result);
Assert.Equal(controller.NotFound(), result);
}
But it doesnt work. Both my IsType<NotFoundResult>(result) and Equal(controller.NotFound(), result) fail. How could i test this please? 😁
87 replies
CC#
Created by Tarkacode on 7/15/2023 in #help
❔ Data Layer communicating ultimately to API controller
Hello 👋 I was wondering if someone has a best practice for this? 😁 I want that my Data Access Layer (Repository using Entity framework) communicates to my API controller to tell it if : 1) If the item to update was not found with corresponding ID in DB 2) If the item to update can not be updated because some item in DB already uses its UNIQUE name 3) If the item has successfully been updated Usually I return to my API the Item if success, or null if not found. But here, I must also communicate if item with unique name already exists, and the controller must know so that I can return valuable info to the API consumer. Do you think that throwing Exception from the data access layer, bubbling it to my Business Layer, and finally catching it in my API Controller is a good idea? I have doubts because some people say exceptions should really be exceptional, and I don't feel like these Database Update impossibilities are really exceptional ? 🤔 Is there another better way to do this ? Any help will be very much appreciated ! 👍
19 replies