1

I am kinda new to this, so my apologizes in advance.

so after (result = await _userManager.UpdateAsync(user);

I get in the logging (DuplicateUserName), be cause the name already exist in another user, So I want to return the validation error to the blazor component and show it to the UI, same validation error that is in the logger

warn: Microsoft.AspNetCore.Identity.UserManager[13] User validation failed: DuplicateUserName.

    [HttpPost("EditSaveUser")]
    public async Task<ActionResult>EditSaveUser(EditUserModel model)
    {
        var user = await _userManager.FindByIdAsync(model.Id);

        if (user == null)
        {
            return BadRequest($"User with Id = {model.Id} cannot be found");
        }
        else
        {
            user.Email = model.Email;
            user.UserName = model.UserName;
            user.City = model.City;

            var result = await _userManager.UpdateAsync(user);

            if (result.Succeeded)
            {
                return Ok(result);
            }
            else
            {
                foreach (var error in result.Errors)
                {
                    ModelState.AddModelError("", error.Description);
                    
                }
                return BadRequest(ModelState);
            }
            
        }

    }

this is the model that has the UserName that i want to apply the validation from the API to it

public class EditUserModel
    {
        public string Id { get; set; }

        [Required]
        public string UserName { get; set; } = string.Empty;
        [Required]
        public string Email { get; set; } = string.Empty;
        public string City { get; set; } = string.Empty;
        public List<string> Claims { get; set; } = new();
        public IList<string> Roles { get; set; }

    }

The model inherent from IdentityUser

public class ApplicationUser : IdentityUser
    {
        public string City { get; set; } = string.Empty;
    }

here i get the response from the API Post

public async Task EditSaveUser(EditUserModel model)
        {
            var result = await _httpClient.PostAsJsonAsync($"https://localhost:7023/api/administration/EditSaveUser/", model);
            
            if (result.IsSuccessStatusCode == false)
            {
                //TODO

            }
        }

here is the code on the blazor component

private EditUserModel model = new();

    protected async override Task OnInitializedAsync()
    {
        var result = await AdminService.EditUser(Id);

        if (result != null)
        {
            model = result;
        }
    }
    private async Task HandleSubmit()
    {
        await AdminService.EditSaveUser(model);
    }

ofc i use

<EditForm Model="model" OnValidSubmit="HandleSubmit">

        <DataAnnotationsValidator/>
        <ValidationSummary />
  <ValidationMessage For="@(()=> model.Email)" />

in Program.cs

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<ApplicationUser>>();
builder.Services.AddScoped<IAdminService,AdminService>();
builder.Services.AddScoped<IAuthService, AuthService>();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddHttpClient();
builder.Services.AddControllers();
builder.Services.AddBlazoredLocalStorage();
builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<AuthenticationStateProvider, ApiAuthenticationStateProvider>();
builder.Services.AddEndpointsApiExplorer();

builder.Services.AddDefaultIdentity<ApplicationUser>()
        .AddRoles<IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>();


builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = builder.Configuration["JwtIssuer"],
        ValidAudience = builder.Configuration["JwtAudience"],
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JwtSecurityKey"]))
    };
});

The model for ApplicationDbContext

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            foreach (var foreignKey in builder.Model.GetEntityTypes().SelectMany(x=> x.GetForeignKeys()))
            {
                foreignKey.DeleteBehavior = DeleteBehavior.Restrict;
            }
        }
    }

I was expecting the UI to get the validation error be cause I am using validation

Anunnaki
  • 11
  • 2
  • I haven't done this before but I think this might help you: https://stackoverflow.com/a/38874151/13440841 – Marvin Klein Nov 08 '22 at 09:27
  • Are you going to get the error message when `result.IsSuccessStatusCode == false`? How do you pass it to the blazor component? – Chen Nov 08 '22 at 09:38
  • Yes it gets statusCode 400 after the duplicate fail in the API, and in the service when result.IsSuccessStatusCode == false just throw new exception when it fails or read the error like this var error = result.Content.ReadAsStringAsync(); i can pass the HTML code to the page after reading it as a string, but i can't get the error to go in the validation – Anunnaki Nov 09 '22 at 10:54

0 Answers0