Open Closed

I am customizing the Login pages here How can I validate the username and password if they are incorrect and show validation error in login page #9061


User avatar
0
Ravikumar-Morrawthu_HON created
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Options;
using Owl.reCAPTCHA;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Account.ExternalProviders;
using Volo.Abp.Account.Public.Web;
using Volo.Abp.Account.Public.Web.Pages.Account;
using Volo.Abp.Account.Security.Recaptcha;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Security.Claims;
using Volo.Abp.Ui.Branding;
using Volo.Saas.Tenants;


namespace Hon.IFS.Admin.Pages.Account
{
    [ExposeServices(typeof(CustomLoginModel), typeof(LoginModel))]
    public class CustomLoginModel : LoginModel
    {
        private readonly ITenantRepository _tenantRepository;
        public  AdminBrandingProvider _adminBrandingProvider;
        public DefaultBrandingProvider _defaultBrandingProvider;
        public IIdentityUserRepository _identityUserRepository;
        public CustomLoginModel(
          IAuthenticationSchemeProvider schemeProvider,
          IOptions<AbpAccountOptions> accountOptions,
          IAccountExternalProviderAppService accountExternalProviderAppService,
          ICurrentPrincipalAccessor currentPrincipalAccessor,
          IAbpRecaptchaValidatorFactory recaptchaValidatorFactory,
          IOptions<IdentityOptions> identityOptions,
          IOptionsSnapshot<reCAPTCHAOptions> reCaptchaOptions,
          ITenantRepository tenantRepository,
          AdminBrandingProvider adminBrandingProvider,
          DefaultBrandingProvider defaultBrandingProvider,
          IIdentityUserRepository identityUserRepository)
          : base(schemeProvider,
            accountOptions,
            recaptchaValidatorFactory,
            accountExternalProviderAppService,
            currentPrincipalAccessor,
            identityOptions,
            reCaptchaOptions)
        {
            _tenantRepository = tenantRepository;
            _adminBrandingProvider = adminBrandingProvider;
            _defaultBrandingProvider = defaultBrandingProvider;
            _identityUserRepository = identityUserRepository;
        }
        public override async Task<IActionResult> OnGetAsync()
        {
            // Decode the entire query string to handle encoded parameters
            var decodedQueryString = Uri.UnescapeDataString(Request.QueryString.ToString());

            // Log the decoded query string for debugging purposes
            System.Diagnostics.Debug.WriteLine(decodedQueryString);

            // Parse the decoded query string manually to extract parameters
            var queryParams = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(decodedQueryString);


            if (queryParams.TryGetValue("tenantKey", out var resolvedTenant))
            {
                _adminBrandingProvider.SetAppName(resolvedTenant.ToString());
                ViewData["sathavva"] = resolvedTenant; 
            }
            return await base.OnGetAsync();
        }
        public override async Task<IActionResult> OnPostAsync(string action)
        {
            // Decode the entire query string to handle encoded parameters
            var decodedQueryString = Uri.UnescapeDataString(Request.QueryString.ToString());


            // Extract the username and password from the posted form data
            var username = Request.Form["LoginInput.UserNameOrEmailAddress"].ToString();
            var password = Request.Form["LoginInput.Password"].ToString(); 

                    // Log the decoded query string for debugging purposes
                    System.Diagnostics.Debug.WriteLine(decodedQueryString);

            // Parse the decoded query string manually to extract parameters
            var queryParams = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(decodedQueryString);

            // Extract the tenantKey from the query parameters
            if (!queryParams.TryGetValue("tenantKey", out var tenantKey))
            {
                //return BadRequest("Tenant key is not provided in the query parameters.");
            }
          //  var resolvedUser = await _identityUserRepository.FindAsync()

            var resolvedTenant = await _tenantRepository.FindByNameAsync(tenantKey);
           // var tenantIdOrName = resolvedTenantId.TenantIdOrName;
            if (resolvedTenant == null)
            {
                // Handle the case where the tenant could not be resolved (e.g., return an error view or redirect).
                //return NotFound("Tenant could not be resolved.");
            }


            // Step 3: Switch tenant and call base login logic with error handling
            try
            {
                using (CurrentTenant.Change(resolvedTenant?.Id, resolvedTenant?.Name ?? "Default"))
                {
                    System.Diagnostics.Debug.WriteLine(CurrentTenant?.Name);

                    // Check ModelState before proceeding (e.g., from data annotations)
                    if (!ModelState.IsValid)
                    {
                        var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage);
                        System.Diagnostics.Debug.WriteLine("Pre-Login Validation Errors: " + string.Join(", ", errors));
                        return Page();
                    }

                    // Call base method with try-catch for additional safety
                    var result = await base.OnPostAsync(action);

                    // Check if base method added errors to ModelState (e.g., invalid credentials)
                    if (!ModelState.IsValid)
                    {
                        var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage);
                        System.Diagnostics.Debug.WriteLine("Post-Login Errors: " + string.Join(", ", errors));
                        return Page();
                    }

                    return result; // Success: redirect or other action result
                }
            }
            catch (Exception ex)
            {
                // Handle exceptions from base login or tenant context switching
                System.Diagnostics.Debug.WriteLine($"Login Processing Error: {ex.Message}");
                ModelState.AddModelError("", "An unexpected error occurred during login. Please try again.");
                return Page();
            }

            //using (CurrentTenant.Change(resolvedTenant?.Id, resolvedTenant?.Name))
            //{
            //    System.Diagnostics.Debug.WriteLine(CurrentTenant?.Name);

            //    // Call base method and handle its result
            //    var result = await base.OnPostAsync(action);

            //    // Check if base method added errors to ModelState
            //    if (!ModelState.IsValid)
            //    {
            //        var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage);
            //        System.Diagnostics.Debug.WriteLine("Post-Login Errors: " + string.Join(", ", errors));
            //        return Page();
            //    }

            //    return result;
            //}
        }
    }

}


7 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    You can use Alerts.Warning(L["Message"]);.

    try
    {
       //...
    }
    catch (Exception ex)
    {
        // Handle exceptions from base login or tenant context switching
        System.Diagnostics.Debug.WriteLine($"Login Processing Error: {ex.Message}");
        ModelState.AddModelError("", "An unexpected error occurred during login. Please try again.");
        
        Alerts.Warning(L["Message"]);
        
        return Page();
    }
    
    
  • User Avatar
    0
    Ravikumar-Morrawthu_HON created
      public override async Task<IActionResult> OnPostAsync(string action)
            {
                // Decode the entire query string to handle encoded parameters
                var decodedQueryString = Uri.UnescapeDataString(Request.QueryString.ToString());
    
    
                // Extract the username and password from the posted form data
                var username = Request.Form["LoginInput.UserNameOrEmailAddress"].ToString();
                var password = Request.Form["LoginInput.Password"].ToString(); 
    
                        // Log the decoded query string for debugging purposes
                        System.Diagnostics.Debug.WriteLine(decodedQueryString);
    
                // Parse the decoded query string manually to extract parameters
                var queryParams = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(decodedQueryString);
    
                // Extract the tenantKey from the query parameters
                if (!queryParams.TryGetValue("tenantKey", out var tenantKey))
                {
                    //return BadRequest("Tenant key is not provided in the query parameters.");
                }
              //  var resolvedUser = await _identityUserRepository.FindAsync()
    
                var resolvedTenant = await _tenantRepository.FindByNameAsync(tenantKey);
               // var tenantIdOrName = resolvedTenantId.TenantIdOrName;
                if (resolvedTenant == null)
                {
                    // Handle the case where the tenant could not be resolved (e.g., return an error view or redirect).
                    //return NotFound("Tenant could not be resolved.");
                }
    
    
                // Step 3: Switch tenant and call base login logic with error handling
                try
                {
                    using (CurrentTenant.Change(resolvedTenant?.Id, resolvedTenant?.Name ?? "Default"))
                    {
                        System.Diagnostics.Debug.WriteLine(CurrentTenant?.Name);
    
                        // Check ModelState before proceeding (e.g., from data annotations)
                        if (!ModelState.IsValid)
                        {
                            var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage);
                            System.Diagnostics.Debug.WriteLine("Pre-Login Validation Errors: " + string.Join(", ", errors));
                            return Page();
                        }
    
                        // Call base method with try-catch for additional safety
                        var result = await base.OnPostAsync(action);
    
                        // Check if base method added errors to ModelState (e.g., invalid credentials)
                        if (!ModelState.IsValid)
                        {
                            var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage);
                            System.Diagnostics.Debug.WriteLine("Post-Login Errors: " + string.Join(", ", errors));
                            return Page();
                        }
    
                        return result; // Success: redirect or other action result
                    }
                }
                catch (Exception ex)
                {
                    // Handle exceptions from base login or tenant context switching
                    System.Diagnostics.Debug.WriteLine($"Login Processing Error: {ex.Message}");
                    ModelState.AddModelError("", "An unexpected error occurred during login. Please try again.");
                    return Page();
                }
    
                //using (CurrentTenant.Change(resolvedTenant?.Id, resolvedTenant?.Name))
                //{
                //    System.Diagnostics.Debug.WriteLine(CurrentTenant?.Name);
    
                //    // Call base method and handle its result
                //    var result = await base.OnPostAsync(action);
    
                //    // Check if base method added errors to ModelState
                //    if (!ModelState.IsValid)
                //    {
                //        var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage);
                //        System.Diagnostics.Debug.WriteLine("Post-Login Errors: " + string.Join(", ", errors));
                //        return Page();
                //    }
    
                //    return result;
                //}
            }
        }
    
    }
    

    Here in the OnPost method. I am not getting Any Exception when I am logging with incorrect password or username

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    The base OnPostAsync method will catch the exception and show an error message in the Login page.

    Can you share why you try to override the page?

    What is your purpose?

    Thanks.

  • User Avatar
    0
    Ravikumar-Morrawthu_HON created

    I want to customize this login page when I am typing incorrect password, I am not getting any error like "Invalid username or password" Alert and it not catching any exception as well. I am following this documentation https://abp.io/docs/2.8/How-To/Customize-Login-Page-MVC Below I am providing my complete code login.chtml @page @using Hon.IFS.Admin @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Abp.Account.Localization @using Volo.Abp.Account.Settings @using Volo.Abp.Account.Web.Pages.Account @using Volo.Abp.AspNetCore.Mvc.UI.Theming @using Volo.Abp.Identity @using Volo.Abp.Settings @model Hon.IFS.Admin.Pages.Account.CustomLoginModel @inject IHtmlLocalizer<AccountResource> L @inject IThemeManager ThemeManager @inject Volo.Abp.Settings.ISettingProvider SettingProvider @inject AdminBrandingProvider adminBrandingProvider

    @{ Layout = ThemeManager.CurrentTheme.GetAccountLayout(); }

    @section scripts { <abp-script-bundle name="@typeof(Hon.IFS.Admin.Pages.Account.CustomLoginModel).FullName"> <abp-script src="/Pages/Account/Login.js" /> </abp-script-bundle> <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.5.1.min.js"></script> <script src="https://ajax.aspnetcdn.com/ajax/jquery.unobtrusive-ajax/3.2.6/jquery.unobtrusive-ajax.min.js"></script> }

    <style> .card-padding { padding: 0.5rem !important; /* Adjusted back to 0.5rem for consistency */ }

    .full-height {
        min-height: 100vh; /* Kept at 100vh for full height */
        display: flex;
        align-items: flex-start; /* Move content to the top */
        padding-top: 50px; /* Adds space from the top to shift content down slightly */
    }
    
    .static-content {
        padding-top: 40px;
        padding-right: 20px;
    }
    
    .red-button {
        background-color: red !important;
        border-color: red !important;
        color: white !important;
    }
    
    .form-check-input.small-switch {
        width: 2em; /* Adjust width */
        height: 1em; /* Adjust height */
    }
    

    </style>

    <div class="row" style="padding-top: 20px; padding-left: 20px"> <div class="col-12 col-md-6 static-content"> <h2 style="color: red">STAY</h2> <h2 style="color: red">CONNECTED</h2> <h2 style="color: white">STAY</h2> <h2 style="color: white">PROTECTED</h2> </div>

    &lt;div class=&quot;col-12 col-md-5 align-content-end pe-md-5&quot;&gt;
        &lt;div style=&quot;display: flex; justify-content: center; align-items: center;&quot;&gt;
            &lt;h3 style=&quot;color: white&quot;&gt;@adminBrandingProvider.AppName&lt;/h3&gt;
        &lt;/div&gt;
    
        &lt;div class=&quot;card shadow-sm rounded card-padding&quot; style=&quot;max-height: 400px; max-width: 600px;&quot;&gt;
            &lt;div class=&quot;card-body p-3&quot;&gt;
                &lt;h3 class=&quot;text-center mb-3&quot;&gt;@L["Login"]&lt;/h3&gt;
    
    
                    &lt;form method=&quot;post&quot; class=&quot;mt-1&quot;&gt;
                        &lt;div class=&quot;mb-1&quot;&gt;
                            &lt;label asp-for=&quot;LoginInput.UserNameOrEmailAddress&quot; class=&quot;form-label&quot;&gt;&lt;/label&gt;
                            &lt;input asp-for=&quot;LoginInput.UserNameOrEmailAddress&quot; class=&quot;form-control form-control-sm&quot; /&gt;
                            &lt;span asp-validation-for=&quot;LoginInput.UserNameOrEmailAddress&quot; class=&quot;text-danger&quot;&gt;&lt;/span&gt;
                        &lt;/div&gt;
                        &lt;div class=&quot;mb-2&quot;&gt;
                            &lt;label asp-for=&quot;LoginInput.Password&quot; class=&quot;form-label&quot;&gt;&lt;/label&gt;
                            &lt;div class=&quot;input-group&quot;&gt;
                                &lt;input type=&quot;password&quot; class=&quot;form-control form-control-sm&quot; autocomplete=&quot;new-password&quot;
                                       maxlength=&quot;@IdentityUserConsts.MaxPasswordLength&quot; asp-for=&quot;LoginInput.Password&quot; /&gt;
                            &lt;/div&gt;
                            &lt;span asp-validation-for=&quot;LoginInput.Password&quot; class=&quot;text-danger&quot;&gt;&lt;/span&gt;
                        &lt;/div&gt;
                    &lt;div class=&quot;row&quot;&gt;
                        &lt;div class=&quot;col&quot;&gt;
                            &lt;div class=&quot;form-check form-switch mb-3&quot;&gt;
                                &lt;input type=&quot;checkbox&quot; class=&quot;form-check-input&quot; id=&quot;LoginInput_RememberMe&quot; name=&quot;LoginInput.RememberMe&quot; value=&quot;true&quot; /&gt;
                                &lt;label class=&quot;form-check-label &quot; for=&quot;LoginInput_RememberMe&quot;&gt;Remember Me&lt;/label&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                        &lt;div class=&quot;col text-end&quot;&gt;
                            &lt;a href=&quot;@Url.Page(&quot;./ForgotPassword&quot;, new { returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash })&quot;&gt;@L["ForgotPassword"]&lt;/a&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                        &lt;div class=&quot;d-grid gap-1&quot;&gt;
                            &lt;abp-button type=&quot;submit&quot; button-type=&quot;Primary&quot; name=&quot;Action&quot; value=&quot;Login&quot; class=&quot;btn-sm mt-2 red-button&quot;&gt;@L["Login"]&lt;/abp-button&gt;
                            @if (Model.ShowCancelButton)
                            {
                                &lt;abp-button type=&quot;submit&quot; button-type=&quot;Secondary&quot; formnovalidate=&quot;formnovalidate&quot; name=&quot;Action&quot; value=&quot;Cancel&quot; class=&quot;btn-sm mt-2&quot;&gt;@L["Cancel"]&lt;/abp-button&gt;
                            }
                        &lt;/div&gt;
                    &lt;/form&gt;
                
       
                
                @if (Model.VisibleExternalProviders.Any())
                {
                    &lt;div class=&quot;mt-1&quot;&gt;
                        &lt;h4&gt;@L["UseAnotherServiceToLogIn"]&lt;/h4&gt;
                        &lt;form asp-page=&quot;./Login&quot; asp-page-handler=&quot;ExternalLogin&quot; asp-route-returnUrl=&quot;@Model.ReturnUrl&quot; asp-route-returnUrlHash=&quot;@Model.ReturnUrlHash&quot; method=&quot;post&quot;&gt;
                            @foreach (var provider in Model.VisibleExternalProviders)
                            {
                                &lt;button type=&quot;submit&quot; class=&quot;btn btn-primary btn-sm m-1&quot; name=&quot;provider&quot; value=&quot;@provider.AuthenticationScheme&quot; title=&quot;@L[&quot;GivenTenantIsNotAvailable&quot;, provider.DisplayName]&quot;&gt;@provider.DisplayName&lt;/button&gt;
                            }
                        &lt;/form&gt;
                    &lt;/div&gt;
                }
    
    
    
           @*      @if (!Model.EnableLocalLogin && !Model.VisibleExternalProviders.Any())
                {
                    &lt;div class=&quot;alert alert-warning&quot;&gt;
                        &lt;strong&gt;@L["InvalidLoginRequest"]&lt;/strong&gt;
                        @L["ThereAreNoLoginSchemesConfiguredForThisClient"]
                    &lt;/div&gt;
                } *@
            &lt;/div&gt;
        &lt;/div&gt;
    
    &lt;/div&gt;
    

    </div>

    login.chtml.cs using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Options; using Owl.reCAPTCHA; using System; using System.Linq; using System.Threading.Tasks; using Volo.Abp.Account.ExternalProviders; using Volo.Abp.Account.Public.Web; using Volo.Abp.Account.Public.Web.Pages.Account; using Volo.Abp.Account.Security.Recaptcha; using Volo.Abp.AspNetCore.MultiTenancy; using Volo.Abp.DependencyInjection; using Volo.Abp.Identity; using Volo.Abp.MultiTenancy; using Volo.Abp.Security.Claims; using Volo.Abp.Ui.Branding; using Volo.Saas.Tenants;

    namespace Hon.IFS.Admin.Pages.Account { [ExposeServices(typeof(CustomLoginModel), typeof(LoginModel))] public class CustomLoginModel : LoginModel { private readonly ITenantRepository _tenantRepository; public AdminBrandingProvider _adminBrandingProvider; public DefaultBrandingProvider _defaultBrandingProvider; public IIdentityUserRepository _identityUserRepository; public CustomLoginModel( IAuthenticationSchemeProvider schemeProvider, IOptions<AbpAccountOptions> accountOptions, IAccountExternalProviderAppService accountExternalProviderAppService, ICurrentPrincipalAccessor currentPrincipalAccessor, IAbpRecaptchaValidatorFactory recaptchaValidatorFactory, IOptions<IdentityOptions> identityOptions, IOptionsSnapshot<reCAPTCHAOptions> reCaptchaOptions, ITenantRepository tenantRepository, AdminBrandingProvider adminBrandingProvider, DefaultBrandingProvider defaultBrandingProvider, IIdentityUserRepository identityUserRepository) : base(schemeProvider, accountOptions, recaptchaValidatorFactory, accountExternalProviderAppService, currentPrincipalAccessor, identityOptions, reCaptchaOptions) { _tenantRepository = tenantRepository; _adminBrandingProvider = adminBrandingProvider; _defaultBrandingProvider = defaultBrandingProvider; _identityUserRepository = identityUserRepository; } public override async Task<IActionResult> OnGetAsync() { // Decode the entire query string to handle encoded parameters var decodedQueryString = Uri.UnescapeDataString(Request.QueryString.ToString());

            // Log the decoded query string for debugging purposes
            System.Diagnostics.Debug.WriteLine(decodedQueryString);
    
            // Parse the decoded query string manually to extract parameters
            var queryParams = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(decodedQueryString);
    
    
            if (queryParams.TryGetValue("tenantKey", out var resolvedTenant))
            {
                _adminBrandingProvider.SetAppName(resolvedTenant.ToString());
                ViewData["sathavva"] = resolvedTenant; 
            }
            return await base.OnGetAsync();
        }
        public override async Task&lt;IActionResult&gt; OnPostAsync(string action)
        {
            // Decode the entire query string to handle encoded parameters
            var decodedQueryString = Uri.UnescapeDataString(Request.QueryString.ToString());
    
    
            // Extract the username and password from the posted form data
            var username = Request.Form["LoginInput.UserNameOrEmailAddress"].ToString();
            var password = Request.Form["LoginInput.Password"].ToString();
    
          
    
                    // Log the decoded query string for debugging purposes
                    System.Diagnostics.Debug.WriteLine(decodedQueryString);
    
            // Parse the decoded query string manually to extract parameters
            var queryParams = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(decodedQueryString);
    
            // Extract the tenantKey from the query parameters
            if (!queryParams.TryGetValue("tenantKey", out var tenantKey))
            {
                //return BadRequest("Tenant key is not provided in the query parameters.");
            }
          //  var resolvedUser = await _identityUserRepository.FindAsync()
    
            var resolvedTenant = await _tenantRepository.FindByNameAsync(tenantKey);
           // var tenantIdOrName = resolvedTenantId.TenantIdOrName;
            if (resolvedTenant == null)
            {
                // Handle the case where the tenant could not be resolved (e.g., return an error view or redirect).
                //return NotFound("Tenant could not be resolved.");
            }
    
    
            // Step 3: Switch tenant and call base login logic with error handling
            try
            {
                using (CurrentTenant.Change(resolvedTenant?.Id, resolvedTenant?.Name ?? "Default"))
                {
                    System.Diagnostics.Debug.WriteLine(CurrentTenant?.Name);
    
                    // Check ModelState before proceeding (e.g., from data annotations)
                    if (!ModelState.IsValid)
                    {
                        var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage);
                        System.Diagnostics.Debug.WriteLine("Pre-Login Validation Errors: " + string.Join(", ", errors));
                        return Page();
                    }
    
                    // Call base method with try-catch for additional safety
                    var result = await base.OnPostAsync(action);
    
                 
    
                   
    
                    // Check if base method added errors to ModelState (e.g., invalid credentials)
                    if (!ModelState.IsValid)
                    {
                        var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage);
                        System.Diagnostics.Debug.WriteLine("Post-Login Errors: " + string.Join(", ", errors));
    
                        // Add custom error message if no specific model errors regarding the username/password
                        ModelState.AddModelError("", "Invalid username or password.");
                        return Page();
                    }
    
                    return result; // Success: redirect or other action result
                }
            }
            catch (Exception ex)
            {
                // Handle exceptions from base login or tenant context switching
                System.Diagnostics.Debug.WriteLine($"Login Processing Error: {ex.Message}");
                ModelState.AddModelError("", "An unexpected error occurred during login. Please try again.");
                Alerts.Warning(L["Message"]);
                return Page();
            }
    
            //using (CurrentTenant.Change(resolvedTenant?.Id, resolvedTenant?.Name))
            //{
            //    System.Diagnostics.Debug.WriteLine(CurrentTenant?.Name);
    
            //    // Call base method and handle its result
            //    var result = await base.OnPostAsync(action);
    
            //    // Check if base method added errors to ModelState
            //    if (!ModelState.IsValid)
            //    {
            //        var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage);
            //        System.Diagnostics.Debug.WriteLine("Post-Login Errors: " + string.Join(", ", errors));
            //        return Page();
            //    }
    
            //    return result;
            //}
        }
    }
    

    }

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you share a test project with your custom code with liming.ma@volosoft.com?

    Thanks

  • User Avatar
    0
    Ravikumar-Morrawthu_HON created
    @await Component.InvokeAsync(typeof(PageAlertsViewComponent))
    

    it resolved after adding this line in index.chtml

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Great. We also use it in theme layout.

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
Do you need assistance from an ABP expert?
Schedule a Meeting
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v9.3.0-preview. Updated on April 16, 2025, 12:13