Customize Security Server-side Blazor

Hi guys, I have been trying to Do the Customize Security part of the CRM Demo with no other tables in the database. The database gets Migrated/Scaffolded correctly, but the FirstName, LastName, and Picture are not being sent/wrote to the database. The Registration, and 2F work fine, (no FirstName, LastName, and Picture). and can change the password. Everything seems to match with the source code, the add and edit forms freeze and give an unable to parse error. Ive done the exercise with Sqlite and MsSql databases with the same results. Anybody else having this issue.

Thanks

Rob

The persistence of those properties is done here: Customize security | Create a Blazor CRM application with Radzen Blazor Studio | Radzen Blazor Studio

Make sure you have not missed this step.

I went thru everything again, I get the error Cannot create user, Unable to parse the response, on the Add and Edit users, the registration page works but doesn't write the extended data to the database. Not sure what else to do. Thanks

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace UserApp.Models
{
    public partial class ApplicationUser
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Picture { get; set; }
        public string Phone { get; set; }

        [NotMapped]
        public string FullName => $"{FirstName} {LastName}";
    }
}
using Microsoft.EntityFrameworkCore;
using UserApp.Models;

namespace UserApp.Data
{
    public partial class AppDbContext
    {
        partial void OnModelBuilding(ModelBuilder builder)
        {
            builder.Entity<ApplicationUser>().ToTable("AspNetUsers");
        }
    }
 }
using System;
using System.Linq;
using UserApp.Models;

namespace UserApp.Controllers
{
    public partial class ApplicationUsersController
    {
        partial void OnUserUpdated(ApplicationUser user)
        {
            var item = context.Users.Where(u => u.Id == user.Id).FirstOrDefault();
            if (user != null)
            {
                item.FirstName = user.FirstName;
                item.LastName = user.LastName;
                item.Picture = user.Picture;
                item.Phone = user.Phone;
            }
        }
    }
}
@page "/register-application-user"

@attribute [Authorize]
<PageTitle>Register Application User</PageTitle>
<RadzenRow>
    <RadzenColumn SizeMD="12">
        <RadzenTemplateForm Data="@user" TItem="UserApp.Models.ApplicationUser"
            Visible="@(user != null)" Submit="@FormSubmit">
            <RadzenAlert Shade="Shade.Lighter" Variant="Variant.Flat" Size="AlertSize.Small" AlertStyle="AlertStyle.Danger" Visible="@errorVisible">@error</RadzenAlert>

            <RadzenStack style="margin-bottom: 1rem;">
                <RadzenFormField Text="Email" Variant="Variant.Filled" >
                    <ChildContent>
                        <RadzenTextBox style="display: block; width: 100%" @bind-Value="@(user.Email)" Name="UserName" />
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="UserName" Text="Email is required" />
                    </Helper>
                </RadzenFormField>
                <RadzenFormField Text="FirstName" Variant="Variant.Filled" >
                    <ChildContent>
                        <RadzenTextBox style="display: block; width: 100%" @bind-Value="@(user.FirstName)" Name="FirstName" />
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="FirstName" Text="First Name is required" />
                    </Helper>
                </RadzenFormField>
                <RadzenFormField Text="LastName" Variant="Variant.Filled" >
                    <ChildContent>
                        <RadzenTextBox style="display: block; width: 100%" @bind-Value="@(user.LastName)" Name="LastName" />
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="LastName" Text="Last Name is required" />
                    </Helper>
                </RadzenFormField>
                <RadzenFormField Text="Phone" Variant="Variant.Filled" >
                    <ChildContent>
                        <RadzenTextBox style="display: block; width: 100%" @bind-Value="@(user.Phone)" Name="Phone" />
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="Phone" Text="Phone Number is required" />
                    </Helper>
                </RadzenFormField>
                <RadzenFormField Text="" Variant="Variant.Filled" >
                    <ChildContent>
                        <RadzenFileInput ChooseText="Choose Picture" @bind-Value="@(user.Picture)" Name="Picture"></RadzenFileInput>
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="Picture" Text="Picture is required" />
                    </Helper>
                </RadzenFormField>
                <RadzenFormField Text="Password" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenPassword @bind-Value="@(user.Password)" style="display: block; width: 100%" Name="Password" />
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="Password" Text="Password is required" />
                    </Helper>
                </RadzenFormField>
                <RadzenFormField Text="Confirm Password" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenPassword style="display: block; width: 100%" @bind-Value="@(user.ConfirmPassword)" Name="ConfirmPassword" />
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="ConfirmPassword" Text="ConfirmPassword is required" />
                    </Helper>
                </RadzenFormField>
            </RadzenStack>
            <RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.End" Gap="0.5rem">
                    <RadzenButton ButtonType="ButtonType.Submit" Icon="save" Text="Register" IsBusy="@isBusy" BusyText="Registering ..." Variant="Variant.Flat" />
                    <RadzenButton ButtonStyle="ButtonStyle.Light" Text="Cancel" Click="@CancelClick" Variant="Variant.Flat" />
            </RadzenStack>
        </RadzenTemplateForm>
    </RadzenColumn>
</RadzenRow>

@page "/add-application-user"
@attribute [Authorize]

<RadzenRow>
    <RadzenColumn SizeMD="12">
        <RadzenTemplateForm TItem="UserApp.Models.ApplicationUser" Data="@user" Visible="@(user != null)" Submit="@FormSubmit">
            <RadzenAlert Title="Cannot create user" Shade="Shade.Lighter" Variant="Variant.Flat" Size="AlertSize.Small" AlertStyle="AlertStyle.Danger" Visible="@errorVisible">@error</RadzenAlert>

            <RadzenStack style="margin-bottom: 1rem;">
                <RadzenFormField Text="Email" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenTextBox style="width: 100%" @bind-Value="@(user.Email)" Name="Email" />
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="Email" Text="Email is required" />
                    </Helper>
                </RadzenFormField>
<RadzenFormField Text="FirstName" Variant="Variant.Filled" >
                    <ChildContent>
                        <RadzenTextBox style="width: 100%" @bind-Value="@(user.FirstName)" Name="FirstName" Placeholder="" />
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="FirstName" Text="First Name is required" />
                    </Helper>
                </RadzenFormField>
<RadzenFormField Text="LastName" Variant="Variant.Filled" >
                    <ChildContent>
                        <RadzenTextBox style="width: 100%" @bind-Value="@(user.LastName)" Name="LastName" Placeholder="" />
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="LastName" Text="Last Name is required" />
                    </Helper>
                </RadzenFormField>
<RadzenFormField Text="Phone" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenTextBox style="width: 100%" @bind-Value="@(user.Phone)" Name="Phone" />
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="Phone" Text="Phone Number is required" />
                    </Helper>
                </RadzenFormField>
<RadzenFormField Text="" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenFileInput ChooseText="Choose Your Picture" @bind-Value="@(user.Picture)" Name="Picture" ></RadzenFileInput>
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="Picture" Text="Picture is required" />
                    </Helper>
                </RadzenFormField>
                 <RadzenFormField Text="Roles" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenDropDown Data="@roles" Multiple="true" style="width: 100%" TextProperty="Name" @bind-Value="@(userRoles)" ValueProperty="Id" Name="Roles" />
                    </ChildContent>
                </RadzenFormField>
                <RadzenFormField Text="Password" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenPassword @bind-Value="@(user.Password)" style="display: block; width: 100%" Name="Password" />
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="Password" Text="Password is required" />
                    </Helper>
                </RadzenFormField>
                <RadzenFormField Text="Confirm Password" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenPassword style="display: block; width: 100%" @bind-Value="@(user.ConfirmPassword)" Name="ConfirmPassword" />
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="ConfirmPassword" Text="ConfirmPassword is required" />
                        <RadzenCompareValidator Text="Passwords must match" Component="ConfirmPassword" Value="@user.Password" />
                    </Helper>
                </RadzenFormField>
            </RadzenStack>
            <RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.End" Gap="0.5rem">
                    <RadzenButton ButtonType="ButtonType.Submit" Icon="save" Text="Save" Variant="Variant.Flat" />
                    <RadzenButton ButtonStyle="ButtonStyle.Light" Text="Cancel" Click="@CancelClick" Variant="Variant.Flat" />
            </RadzenStack>
        </RadzenTemplateForm>
    </RadzenColumn>
</RadzenRow>```

@page "/edit-application-user/{Id}"
@attribute [Authorize]

<RadzenRow>
    <RadzenColumn SizeMD="12">
        <RadzenTemplateForm TItem="UserApp.Models.ApplicationUser" Data="@user" Visible="@(user != null)" Submit="@FormSubmit">
            <RadzenAlert Title="Cannot update user" Shade="Shade.Lighter" Variant="Variant.Flat" Size="AlertSize.Small" AlertStyle="AlertStyle.Danger" Visible="@errorVisible">@error</RadzenAlert>

            <RadzenStack style="margin-bottom: 1rem;">
                <RadzenFormField Text="User name" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenTextBox Disabled="true" style="width: 100%" @bind-Value="@(user.UserName)" Name="UserName" />
                    </ChildContent>
                </RadzenFormField>
                <RadzenFormField Text="Email" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenTextBox style="width: 100%" @bind-Value="@(user.Email)" Name="Email" />
                    </ChildContent>
                </RadzenFormField>
                <RadzenFormField Text="FirstName" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenTextBox style="width: 100%" @bind-Value="@(user.FirstName)" Name="FirstName" />
                    </ChildContent>
                </RadzenFormField>
                <RadzenFormField Text="LastName" Variant="Variant.Filled" >
                    <ChildContent>
                        <RadzenTextBox style="width: 100%" @bind-Value="@(user.LastName)" Name="LastName" />
                    </ChildContent>
                </RadzenFormField>
                <RadzenFormField Text="Phone" Variant="Variant.Filled" >
                    <ChildContent>
                        <RadzenTextBox style="width: 100%" @bind-Value="@(user.Phone)" Name="Phone" />
                    </ChildContent>
                </RadzenFormField>
                <RadzenFormField Text="" Variant="Variant.Filled" >
                    <ChildContent>
                        <RadzenFileInput @bind-Value="@(user.Picture)" ChooseText="Update Your Picture" Name="Picture"></RadzenFileInput>
                    </ChildContent>
                </RadzenFormField>
                 <RadzenFormField Text="Role" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenDropDown Data="@roles" Multiple="true" style="width: 100%" TextProperty="Name" @bind-Value="@(userRoles)" ValueProperty="Id" Name="Roles" />
                    </ChildContent>
                </RadzenFormField>
                <RadzenFormField Text="Password" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenPassword @bind-Value="@(user.Password)" style="display: block; width: 100%" Name="Password" />
                    </ChildContent>
                    <Helper>
                        <RadzenRequiredValidator Component="Password" Text="Password is required" />
                    </Helper>
                </RadzenFormField>
                <RadzenFormField Text="Confirm Password" Variant="Variant.Filled">
                    <ChildContent>
                        <RadzenPassword style="display: block; width: 100%" @bind-Value="@(user.ConfirmPassword)" Name="ConfirmPassword" />
                    </ChildContent>
                    <Helper>
                        <RadzenCompareValidator Text="Passwords must match" Component="ConfirmPassword" Value="@user.Password" />
                    </Helper>
                </RadzenFormField>
            </RadzenStack>
            <RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.End" Gap="0.5rem">
                    <RadzenButton ButtonType="ButtonType.Submit" Icon="save" Text="Save" Variant="Variant.Flat" />
                    <RadzenButton ButtonStyle="ButtonStyle.Light" Text="Cancel" Click="@CancelClick" Variant="Variant.Flat" />
            </RadzenStack>
        </RadzenTemplateForm>
    </RadzenColumn>
</RadzenRow>

The source code of this app is available online. Compare it with your implementation.

I'm not sure if I need the RadzenCRMService.Custom.cs, Im not making a CRM App, and dont have the CRM tables in the database. I'm just trying to customize the user management part of the exercise, to have a customized user manager template to start from. I've gone thru the source code multiple times, copy/pasted the code and can't get it to work.

Thanks

Rob

I'm not seeing what step I missed, Ive gone thru this process about ten times now I dont know why this isn't working. I get the error:

Thanks.

Rob

fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
      System.NullReferenceException: Object reference not set to an instance of an object.
         at UserApp4.Controllers.ApplicationUsersController.Post(ApplicationUser user) in C:\Users\Rob31\source\Projects\UA4\Controllers\ApplicationUsersController.cs:line 137
         at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_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.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
         at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
info: System.Net.Http.HttpClient.UserApp4.ClientHandler[101]
      Received HTTP response headers after 95.5152ms - 500
info: System.Net.Http.HttpClient.UserApp4.LogicalHandler[101]
      End processing HTTP request after 95.6309ms - 500

What does UserApp4.Controllers.ApplicationUsersController.Post line 137 do?

The code you posted above refers to a namespace UserApp.Controllers

I'm doing everything the CRM Example shows. I'm stumped.

Thanks

[HttpPost]
        public async Task<IActionResult> Post([FromBody] ApplicationUser user)
        {
      137_>      user.UserName = user.Email;            
            user.EmailConfirmed = true;
            var password = user.Password;
            var roles = user.Roles;
            user.Roles = null;
            IdentityResult result = await userManager.CreateAsync(user, password);

I just followed the instructions posted above by @korchev for customizing the ApplicationUser for just FirstName and LastName and it all worked as expected.
You might need to run the application in debug mode to find why user is not being passed thru.

In the ApplicationUser.Custom.cs, I had the line

[NotMapped]
public string FullName => $"{FirstName} {LastName}";

As soon as I deleted that out, everything worked fine.

Thanks for your Help.

You can try adding [JsonIgnore] to FullName