balessi75的活动

Hi @balessi75,

Can you share the full content of Register.cshtml & Register.cshtml.cs files?

Also, what does the error/exception say?

Hi @yekalkan,

The user friendly message is our message from an overriden AccountAppService RegisterAsync method call.

Here is the Rgister.cshtml:

@page
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@using Volo.Abp.Account.Public.Web.Security.Recaptcha
@using Volo.Abp.Account.Security.Recaptcha
@using Volo.Abp.Account.Settings
@using Volo.Abp.Settings
@using Volo.Abp.BlazoriseUI.Components
@model FM.Timepiece.Blazor.Pages.Account.TimepieceRegisterModel
@*@model Volo.Abp.Account.Public.Web.Pages.Account.RegisterModel*@
@inject IHtmlLocalizer<AccountResource> L
@inject Volo.Abp.AspNetCore.Mvc.UI.Layout.IPageLayout PageLayout
@inject ISettingProvider SettingProvider
@{
    PageLayout.Content.Title = L["Register"].Value;
    var reCaptchaVersion = await SettingProvider.GetAsync<int>(AccountSettingNames.Captcha.Version);
}


@section scripts
{
    @if (Model.UseCaptcha)
    {
        if (reCaptchaVersion == 3)
        {
            <recaptcha-script-v3/>
            <recaptcha-script-v3-js action="register" callback="(function(){$('#@RecaptchaValidatorBase.RecaptchaResponseKey').val(token)})"/>
        }
        else
        {
            <recaptcha-script-v2/>
        }
    }


}

<div class="account-module-form">
    <form method="post">

        @if (Model.UseCaptcha)
        {
            <input type="hidden" name="@RecaptchaValidatorBase.RecaptchaResponseKey" id="@RecaptchaValidatorBase.RecaptchaResponseKey"/>
        }
 
        
        @if (!Model.IsExternalLogin)
        {
              <abp-row>
                <abp-column size="_6">
                    <abp-input asp-for="Input.UserName" label="User Name" auto-focus="true"/>
                </abp-column>
                <abp-column size="_6">
                     <abp-input asp-for="Input.Password" label="Password"/>
                </abp-column>     
            </abp-row>  
          
        }
        
        <abp-row>
            <abp-column size="_6">
                <abp-input asp-for="Input.EmailAddress" label="Email Address"/> 
            </abp-column>
            <abp-column size="_6">
                <abp-input asp-for="Input.EmployeeId" label="Employee Id"/> 
            </abp-column>
        </abp-row>
   
         <abp-row>
            <abp-column size="_6">
                  <abp-input asp-for="Input.FirstName" label="First Name"/>
            </abp-column>
            <abp-column size="_6">
                  <abp-input asp-for="Input.LastName" label="Last Name"/>
            </abp-column>
        </abp-row>

        <abp-row>
            <abp-column size="_6">
                  <abp-input asp-for="Input.ZipCode" label="Zip Code"/>
            </abp-column>
            <abp-column size="_6">

            
               <abp-input asp-for="Input.DateOfBirth" label="Date Of Birth"/>
                 
            </abp-column>
        </abp-row>


        @if (reCaptchaVersion == 2)
        {
            <recaptcha-div-v2 callback="(function(){$('#@RecaptchaValidatorBase.RecaptchaResponseKey').val(token)})" />
        }

        <div class="d-grid gap-2">
            <abp-button button-type="Primary" type="submit" class="mt-2 mb-3">@L["Register"]</abp-button>
        </div>
        @L["AlreadyRegistered"] <a href="@Url.Page("./Login", new {returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash})">@L["Login"]</a>
    </form>
</div>

And register.chtml.cs

using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Owl.reCAPTCHA;
using Volo.Abp.Account.Public.Web.Security.Recaptcha;
using Volo.Abp.Account.Settings;
using Volo.Abp.Auditing;
using Volo.Abp.Identity;
using Volo.Abp.Identity.Settings;
using Volo.Abp.Security.Claims;
using Volo.Abp.Settings;
using Volo.Abp.Uow;
using Volo.Abp.Validation;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
using Volo.Abp.Account.Public.Web.Pages.Account;
using Volo.Abp;
using Volo.Abp.Account;
using FM.Timepiece.Identity;
using System;
using FM.Timepiece.Account;
using Volo.Abp.Data;
using FM.Timepiece.Employees;

//namespace Volo.Abp.Account.Public.Web.Pages.Account;
namespace FM.Timepiece.Blazor.Pages.Account;

public class TimepieceRegisterModel : AccountPageModel
{
    [BindProperty(SupportsGet = true)]
    public string ReturnUrl { get; set; }

    [BindProperty(SupportsGet = true)]
    public string ReturnUrlHash { get; set; }

    [BindProperty]
    public PostInput Input { get; set; }

    [BindProperty(SupportsGet = true)]
    public bool IsExternalLogin { get; set; }

    [BindProperty(SupportsGet = true)]
    public string ExternalLoginAuthSchema { get; set; }

    public bool UseCaptcha { get; set; }

    public virtual async Task<IActionResult> OnGetAsync()
    {
        await CheckSelfRegistrationAsync();
        await TrySetEmailAsync();
        await SetUseCaptchaAsync();

        return Page();
    }

    [UnitOfWork] //TODO: Will be removed when we implement action filter
    public virtual async Task<IActionResult> OnPostAsync()
    {
        try
        {
            await CheckSelfRegistrationAsync();
            await SetUseCaptchaAsync();

            IdentityUser user;
            if (IsExternalLogin)
            {
                var externalLoginInfo = await SignInManager.GetExternalLoginInfoAsync();
                if (externalLoginInfo == null)
                {
                    Logger.LogWarning("External login info is not available");
                    return RedirectToPage("./Login");
                }

                user = await RegisterExternalUserAsync(externalLoginInfo, Input.EmailAddress);
            }
            else
            {
                user = await RegisterLocalUserAsync();
            }

            //
            //Timepiece override to always require a confirmed email during the registration process for security reasons
            //

            //if (await SettingProvider.IsTrueAsync(IdentitySettingNames.SignIn.RequireConfirmedEmail) && !user.EmailConfirmed ||
            //    await SettingProvider.IsTrueAsync(IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber) && !user.PhoneNumberConfirmed)
            //{
                await StoreConfirmUser(user);

                return RedirectToPage("./ConfirmUser", new {
                    returnUrl = ReturnUrl,
                    returnUrlHash = ReturnUrlHash
                });
           // }

            //await SignInManager.SignInAsync(user, isPersistent: true);

            //return Redirect(ReturnUrl ?? "/"); //TODO: How to ensure safety? IdentityServer requires it however it should be checked somehow!
        }
        catch (BusinessException e)
        {
            Alerts.Danger(GetLocalizeExceptionMessage(e));

            Input.DateOfBirth = DateTime.Now;
            return Page();
        }
    }

    protected virtual async Task<IdentityUser> RegisterLocalUserAsync()
    {
        ValidateModel();

        var captchaResponse = string.Empty;
        if (UseCaptcha)
        {
            captchaResponse = HttpContext.Request.Form[RecaptchaValidatorBase.RecaptchaResponseKey];
        }

        var registerDto = new RegisterDto
        {
            AppName = "MVC",
            EmailAddress = Input.EmailAddress,
            Password = Input.Password,
            UserName = Input.UserName,
            ReturnUrl = ReturnUrl,
            ReturnUrlHash = ReturnUrlHash,
            CaptchaResponse = captchaResponse
        };
        registerDto.SetProperty(EmployeeConsts.EmployeeId, Input.EmployeeId);
        registerDto.SetProperty(EmployeeConsts.FirstName, Input.FirstName);
        registerDto.SetProperty(EmployeeConsts.LastName, Input.LastName);
        registerDto.SetProperty(EmployeeConsts.ZipCode, Input.ZipCode);
        registerDto.SetProperty(EmployeeConsts.DateOfBirth, Input.DateOfBirth);

        var userDto = await AccountAppService.RegisterAsync(registerDto);

        return await UserManager.GetByIdAsync(userDto.Id);
    }

    protected virtual async Task<IdentityUser> RegisterExternalUserAsync(ExternalLoginInfo externalLoginInfo, string emailAddress)
    {
        await IdentityOptions.SetAsync();

        var user = new IdentityUser(GuidGenerator.Create(), emailAddress, emailAddress, CurrentTenant.Id);

        (await UserManager.CreateAsync(user)).CheckErrors();
        (await UserManager.AddDefaultRolesAsync(user)).CheckErrors();

        if (!user.EmailConfirmed)
        {
            await AccountAppService.SendEmailConfirmationTokenAsync(
                new SendEmailConfirmationTokenDto
                {
                    AppName = "MVC",
                    UserId = user.Id,
                    ReturnUrl = ReturnUrl,
                    ReturnUrlHash = ReturnUrlHash
                }
            );
        }

        var userLoginAlreadyExists = user.Logins.Any(x =>
            x.TenantId == user.TenantId &&
            x.LoginProvider == externalLoginInfo.LoginProvider &&
            x.ProviderKey == externalLoginInfo.ProviderKey);

        if (!userLoginAlreadyExists)
        {
            user.AddLogin(new UserLoginInfo(
                    externalLoginInfo.LoginProvider,
                    externalLoginInfo.ProviderKey,
                    externalLoginInfo.ProviderDisplayName
                )
            );

            (await UserManager.UpdateAsync(user)).CheckErrors();
        }

        return user;
    }

    protected virtual async Task CheckSelfRegistrationAsync()
    {
        if (!await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled) ||
            !await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin))
        {
            throw new UserFriendlyException(L["SelfRegistrationDisabledMessage"]);
        }
    }

    protected virtual async Task SetUseCaptchaAsync()
    {
        UseCaptcha = !IsExternalLogin && await SettingProvider.IsTrueAsync(AccountSettingNames.Captcha.UseCaptchaOnRegistration);
        if (UseCaptcha)
        {
            var reCaptchaVersion = await SettingProvider.GetAsync<int>(AccountSettingNames.Captcha.Version);
            await ReCaptchaOptions.SetAsync(reCaptchaVersion == 3 ? reCAPTCHAConsts.V3 : reCAPTCHAConsts.V2);
        }
    }

    protected virtual async Task StoreConfirmUser(IdentityUser user)
    {
        var identity = new ClaimsIdentity(ConfirmUserModel.ConfirmUserScheme);
        identity.AddClaim(new Claim(AbpClaimTypes.UserId, user.Id.ToString()));
        if (user.TenantId.HasValue)
        {
            identity.AddClaim(new Claim(AbpClaimTypes.TenantId, user.TenantId.ToString()));
        }
        await HttpContext.SignInAsync(ConfirmUserModel.ConfirmUserScheme, new ClaimsPrincipal(identity));
    }

    private async Task TrySetEmailAsync()
    {
        if (IsExternalLogin)
        {
            var externalLoginInfo = await SignInManager.GetExternalLoginInfoAsync();
            if (externalLoginInfo == null)
            {
                return;
            }

            if (!externalLoginInfo.Principal.Identities.Any())
            {
                return;
            }

            var identity = externalLoginInfo.Principal.Identities.First();
            var emailClaim = identity.FindFirst(ClaimTypes.Email);

            if (emailClaim == null)
            {
                return;
            }

            Input = new PostInput { EmailAddress = emailClaim.Value };
        }
    }

    public class PostInput
    {
        [Required]
        [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxUserNameLength))]
        public string UserName { get; set; }

        [Required]
        [EmailAddress]
        [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxEmailLength))]
        public string EmailAddress { get; set; }

        [Required]
        [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))]
        [DataType(DataType.Password)]
        [DisableAuditing]
        public string Password { get; set; }

        //Added for Timepiece employee verification

        [Required(ErrorMessage = "Employee Id is required")]
        public int EmployeeId { get; set; }

        [Required(ErrorMessage = "First Name Name is required")]
        [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxNameLength))]
        public string FirstName { get; set; }

        [Required(ErrorMessage = "Last Name is required")]
        [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxSurnameLength))]
        public string LastName { get; set; }

        [Required(ErrorMessage = "Zip Code is required")]
        [RegularExpression(@"(^\d{5}$)|(^\d{9}$)|(^\d{5}-\d{4}$)", ErrorMessage = "Invalid Zip Code")]
        [DynamicStringLength(typeof(UserConsts), nameof(UserConsts.MaxZipCodeLength))]
        public string ZipCode { get; set; }

        [Required(ErrorMessage = "Date Of Birth is required")]
        [DataType(DataType.Date)]
        [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
        public DateTime DateOfBirth { get; set; }
    }
}

Abp Commercial 5.1.3

We have a requirement to override the Register.cshtml page by adding a DateOfBirth input field. It is defined as follows..

The field works as expected, except for the fact that it's value is cleared on post when when the Register App Service returns a user friendly exception and the user friendly error is shown at the top of the register dialog. All other input fields retain their value.

Is there something simple I'm missing here? Any work arounds to get the input to retain it's selected date when posting with validation errors?

Ok, thanks. Will do for our pages, but we were hoping to have this in the dependent Abp modules as well without overriding the Abp pages.

Abp Commercial 5.1.3 / EF / Blazor Server

The EasyCRM demo and examples in project types other than Blazor feature the ability for the user to specify the paging size on data grids...

However, we do not see this feature in the base modules of Blazor Server. Is this just not implemented yet in Blazor or is there a way to turn this feature on? We have a requirement to have a grid footer shown like above.

Thanks in advance. Brian

Ok, so the refactoring will be in a future release?

Can you clarify on what source code to copy and to where/how?

Abp 4.4.3 Commercial (Enterprise) / Blazor Server / EF

Hello, We need to customize the ordering of permission groups in the permission management modal. We used the following document as a reference... https://docs.abp.io/en/abp/4.4/UI/Blazor/Customization-Overriding-Components

Under ...Blazor\Components in our solution, we created a MyPermissionManagmentModal.razor and MyPermissionManagementModal.razor.cs file. We then copied the corresponding source from... https://github.com/abpframework/abp/tree/rel-4.4/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components into our razor and razor code-behind file.

Our MyPermissionManagementModal inherits from Abp's PermissionManagmentModal and we decorated our Modal with... [ExposeServices(typeof(PermissionManagementModal))] [Dependency(ReplaceServices = true)]

At runtime, we can see that a breakpoint is hit in the constructor of MyPermissionManagementModal which is good, however, when we click to open the modal, we receive the following... An internal error occurred during your request! 2022-01-18 16:21:58.742 -05:00 [ERR] Delegate to an instance method cannot have null 'this'. System.ArgumentException: Delegate to an instance method cannot have null 'this'. at System.MulticastDelegate.ThrowNullThisInDelegateToInstance() at Volo.Abp.PermissionManagement.Blazor.Components.PermissionManagementModal.OpenAsync(String providerName, String providerKey, String entityDisplayName)

A break point in our modal at OpenAsync never gets hit.

We are at a loss as to where to go from here and are wondering if we are attempting to solve this problem in an incorrect way. Any help would be greatly appreciated.

Thank you!

Hi, This setting almost satisfies our requirements. I'm assuming this setting applies to both Registering and Logging In, correct?. What we actually need is for the system to always require Email or Phone verification in order to register, and then have these settings to be able to be turned on and off for just signing in.

Any guidance as to how to accomplish that would be greatly appreciated.

Hi Spospisil, I had ran into the exact same problem, but was forced to implement IMultiTenancy even with separate databases for each tenant. I am using version 4.4.3 though.

Are you still running into this issue?

Hi, We are using ABP version 4.4.3, Blazor Server, EF Core

Does ABP provide the ability to setup and require email and/or text verification prior to self-registration? We are having difficulty finding ABP documentation on this. We did find this community article https://community.abp.io/articles/setup-email-confirmation-on-user-registration-q0vgxang But much of it appears to not be applicable to Blazor Server.

Any guidance would be much appreciated. Thanks.

  • ABP Framework version: v4.4.3
  • UI type: Blazor Server
  • DB provider: EF Core

We see examples of rendering a grid using the approach of <DataGrid ....> <DataGridColumns...> <DataGridColumn...> where each column's definition is defined in the .razor file markup. We also see examples of using <AbpExtensibleDataGrid...> where all of the grids column specifications are defined in the razor.cs code behind file in C#.

Which approach is generally recommended and under what senario would you use one approach or the other?

Thanks as always!

显示 236 个条目中的 221 到 230 个.
Made with ❤️ on ABP v8.2.0-preview Updated on 三月 25, 2024, 15:11