I tried this solution, and it's redirecting the user directly into it's profile. However, because we have put the condition that if the user is not authenticated, it should simply be redirected to the login page, I won't be able to use the landing page of the angular application.
As soon as, I try to access this page, it will redirect the user to the login page and I don't want that. I'll need that page in use.
Isn't there any way we can configure it from the Auth Server side? So that it directly redirects the user into it's profile as soon as the login button is clicked? Please suggest.
But will it work on the Auth Server as well? Because our Auth Server is an MVC project, separate from angular.
yCheck the docs before asking a question: https://docs.abp.io/en/commercial/latest/ Check the samples to see the basic tasks: https://docs.abp.io/en/commercial/latest/samples/index The exact solution to your question may have been answered before, and please first use the search on the homepage. Provide us with the following info:
We have a global-styles.css file to apply customized css in our applicaton. But it's not showing any impact on the Auth Server project that we have. It's not applying there. Can you tell us how can we achieve that?
I have done some customization in my Auth-Server project (MVC). When I enter my user credentials and click on Login button, it redirects me to my angular application (I have done customization for it in the Login.cshtml.cs file, on OnPostAsync method I am returning my Angular app's url).
ConfigValues.AngularAppUrl holds my angular app url
return Redirect(ConfigValues.AngularAppUrl);
The problem is, when I click on the Login button, it does redirect to the angular app, but it will not be logged in as a user but rather just the outside page of it. And once and only when I click on the login icon on my angular application page, then it will log in as a user (see the flow below).
I want a way where on clicking the Login button in the Auth Server (first image), I should be redirected to the angular application with user logged in.
This will work, but it's basically calling the API again to get the details of the input fields, and that doesn't sound great. Can you give me something else? Something which can hold the values of the variable till the page is refreshed or the instance of the class is destroyed.
If you run this, now you will see that it works and it will hold the values, but here I have done a work around. I have created a separate input field for all the properties and I am keeping them hidden for now, because that's the only way I could find in order to hold the values. I'd like something more proper to do that.
For example :
<input type="hidden" asp-for="@Model.Fields[i].Index" />
<input type="hidden" asp-for="@Model.Fields[i].Title" />
<input type="hidden" asp-for="@Model.Fields[i].IsRequired" />
<input type="hidden" asp-for="@Model.Fields[i].HasOtherOption" />
<input type="hidden" asp-for="@Model.Fields[i].QuestionType" />
<input type="hidden" asp-for="@Model.Fields[i].Choices" />
Yeah, here you go.
@page @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Abp.Account.Localization @using Volo.Abp.Account.Public.Web.Security.Recaptcha @using Volo.Abp.Account.Settings @using Volo.Abp.Settings @model G1.health.AuthServer.Pages.Account.RegisterModel @using Volo.Forms; @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); }
@if (!Model.LocalLoginDisabled) { @section scripts { <abp-script-bundle name="@typeof(G1.health.AuthServer.Pages.Account.RegisterModel).FullName"> <abp-script src="/Pages/Account/Register.js" /> </abp-script-bundle>
@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 />
}
}
}
<style>
.hidden-scroll::-webkit-scrollbar {
display: none;
}
.hidden-scroll{
height: 500px;
overflow: scroll
}
</style>
<div class="account-module-form hidden-scroll">
<h5 class="mb-2">@L["AlreadyRegistered"] <a class="text-decoration-none" href="@Url.Page("./Login", new {returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash})">@L["Login"]</a></h5>
<form method="post">
@if (Model.UseCaptcha)
{
<div class="mb-2">
<input type="hidden" name="@RecaptchaValidatorBase.RecaptchaResponseKey" id="@RecaptchaValidatorBase.RecaptchaResponseKey" />
</div>
}
@if (!Model.IsExternalLogin)
{
<div class="form-floating mb-2">
<input asp-for="Input.UserName" type="text" class="form-control" placeholder="name@example.com" auto-focus="true">
@Html.LabelFor(m => m.Input.UserName)
</div>
}
<div class="form-floating mb-2">
<input asp-for="Input.EmailAddress" type="email" class="form-control" placeholder="name@example.com" auto-focus="true">
@Html.LabelFor(m => m.Input.EmailAddress)
</div>
@if (!Model.IsExternalLogin)
{
<div class="form-floating mb-2">
<input asp-for="Input.Password" id="password-input" type="password" class="form-control" placeholder="Password">
@Html.LabelFor(m => m.Input.Password)
<i id="PasswordVisibilityButton" class="bi bi-eye-slash show-pass-icon" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-html="true" aria-label="@L["ShowPassword"]" data-bs-original-title="@L["ShowPassword"]"></i>
<i id="capslockicon" class="bi bi-capslock caps-lock-icon" style="display: none;" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-html="true" aria-label="<i class='bi bi-exclamation-circle'></i> @L["CapsLockOn"]!" data-bs-original-title="<i class='bi bi-exclamation-circle'></i> @L["CapsLockOn"]!"></i>
</div>
}
@for (int i = 0; i < Model.Fields.Count; i++)
{
switch (Model.Fields[i].QuestionType)
{
case QuestionTypes.ShortText:
<div class="form-floating mb-2">
<input type="hidden" asp-for="@Model.Fields[i].Index" />
<input type="hidden" asp-for="@Model.Fields[i].Title" />
<input type="hidden" asp-for="@Model.Fields[i].IsRequired" />
<input type="hidden" asp-for="@Model.Fields[i].QuestionType" />
<input asp-for="@Model.Fields[i].Answer" required="@Model.Fields[i].IsRequired" type="text" class="form-control" auto-focus="true">
@Html.Label(Model.Fields[i].Title)
</div>
break;
case QuestionTypes.ParagraphText:
<div class="form-floating mb-2">
<input type="hidden" asp-for="@Model.Fields[i].Index" />
<input type="hidden" asp-for="@Model.Fields[i].Title" />
<input type="hidden" asp-for="@Model.Fields[i].IsRequired" />
<input type="hidden" asp-for="@Model.Fields[i].QuestionType" />
<input asp-for="@Model.Fields[i].Answer" required="@Model.Fields[i].IsRequired" type="text" class="form-control" auto-focus="true">
@Html.Label(Model.Fields[i].Title)
</div>
break;
case QuestionTypes.ChoiceMultiple:
<div class="form-floating mb-2">
<input type="hidden" asp-for="@Model.Fields[i].Index" />
<input type="hidden" asp-for="@Model.Fields[i].Title" />
<input type="hidden" asp-for="@Model.Fields[i].IsRequired" />
<input type="hidden" asp-for="@Model.Fields[i].HasOtherOption" />
<input type="hidden" asp-for="@Model.Fields[i].QuestionType" />
<input type="hidden" asp-for="@Model.Fields[i].Choices" />
<lable>@Model.Fields[i].Title</lable>
<abp-radio asp-for="@Model.Fields[i].Answer" required="@Model.Fields[i].IsRequired" asp-items="@Model.Fields[i].Choices" />
</div>
break;
case QuestionTypes.Checkbox:
<div class="form-floating mb-2">
<input type="hidden" asp-for="@Model.Fields[i].Index" />
<input type="hidden" asp-for="@Model.Fields[i].Title" />
<input type="hidden" asp-for="@Model.Fields[i].IsRequired" />
<input type="hidden" asp-for="@Model.Fields[i].HasOtherOption" />
<input type="hidden" asp-for="@Model.Fields[i].QuestionType" />
<input type="hidden" asp-for="@Model.Fields[i].Choices" />
@foreach (var choice in Model.Fields[i].Choices)
{
<abp-input asp-for="@Model.Fields[i].Answer" required="@Model.Fields[i].IsRequired" label="@choice.Value" type="checkbox" />
}
</div>
break;
case QuestionTypes.DropdownList:
<div class="form-floating mb-2">
<input type="hidden" asp-for="@Model.Fields[i].Index" />
<input type="hidden" asp-for="@Model.Fields[i].Title" />
<input type="hidden" asp-for="@Model.Fields[i].IsRequired" />
<input type="hidden" asp-for="@Model.Fields[i].HasOtherOption" />
<input type="hidden" asp-for="@Model.Fields[i].QuestionType" />
<input type="hidden" asp-for="@Model.Fields[i].Choices" />
<abp-select asp-for="@Model.Fields[i].Answer" required="@Model.Fields[i].IsRequired" label="@Model.Fields[i].Title" asp-items="@Model.Fields[i].Choices" />
</div>
break;
case QuestionTypes.MultipleSelect:
<div class="form-floating mb-2">
<input type="hidden" asp-for="@Model.Fields[i].Index" />
<input type="hidden" asp-for="@Model.Fields[i].Title" />
<input type="hidden" asp-for="@Model.Fields[i].IsRequired" />
<input type="hidden" asp-for="@Model.Fields[i].HasOtherOption" />
<input type="hidden" asp-for="@Model.Fields[i].QuestionType" />
<input type="hidden" asp-for="@Model.Fields[i].Choices" />
<abp-select asp-for="@Model.Fields[i].Answers" required="@Model.Fields[i].IsRequired" label="@Model.Fields[i].Title" asp-items="@Model.Fields[i].Choices" />
</div>
break;
case QuestionTypes.Calendar:
<div class="form-floating mb-2">
<input type="hidden" asp-for="@Model.Fields[i].Index" />
<input type="hidden" asp-for="@Model.Fields[i].Title" />
<input type="hidden" asp-for="@Model.Fields[i].IsRequired" />
<input type="hidden" asp-for="@Model.Fields[i].QuestionType" />
<input asp-for="@Model.Fields[i].Answer" required="@Model.Fields[i].IsRequired" type="datetime-local" class="form-control" auto-focus="true" />
@Html.Label(Model.Fields[i].Title)
</div>
break;
case QuestionTypes.Date:
<div class="form-floating mb-2">
<input type="hidden" asp-for="@Model.Fields[i].Index" />
<input type="hidden" asp-for="@Model.Fields[i].Title" />
<input type="hidden" asp-for="@Model.Fields[i].IsRequired" />
<input type="hidden" asp-for="@Model.Fields[i].QuestionType" />
<input asp-for="@Model.Fields[i].Answer" required="@Model.Fields[i].IsRequired" type="date" class="form-control" auto-focus="true">
@Html.Label(Model.Fields[i].Title)
</div>
break;
case QuestionTypes.Time:
<div class="form-floating mb-2">
<input type="hidden" asp-for="@Model.Fields[i].Index" />
<input type="hidden" asp-for="@Model.Fields[i].Title" />
<input type="hidden" asp-for="@Model.Fields[i].IsRequired" />
<input type="hidden" asp-for="@Model.Fields[i].QuestionType" />
<input asp-for="@Model.Fields[i].Answer" required="@Model.Fields[i].IsRequired" type="time" class="form-control" auto-focus="true">
@Html.Label(Model.Fields[i].Title)
</div>
break;
}
}
@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>
</form>
</div>
}
Sure, here it is.
If you see here in the following form, you'd see 2 input fields i.e., Name and Gender, the details of which are being fetched from the database from an API endpoint. And those fields will be generated dynamically on run time.
Now, once I put all the details, and click on Register, those 2 fields will be disappeared.
Here is my code as well :
Register.cshtml.cs file :
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using G1.health.ClinicService.ClinicSetup;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Owl.reCAPTCHA;
using survey.FormsService.Forms;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.Public.Web.Pages.Account;
using Volo.Abp.Account.Public.Web.Security.Recaptcha;
using Volo.Abp.Account.Settings;
using Volo.Abp.AspNetCore.Mvc.MultiTenancy;
using Volo.Abp.Auditing;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Identity;
using Volo.Abp.Identity.EntityFrameworkCore;
using Volo.Abp.Identity.Settings;
using Volo.Abp.Security.Claims;
using Volo.Abp.Settings;
using Volo.Abp.Uow;
using Volo.Abp.Validation;
using Volo.Forms;
using Volo.Forms.Questions;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace G1.health.AuthServer.Pages.Account;
public class RegisterModel : Web.Pages.Account.AccountPageModel
{
public IAbpTenantAppService AbpTenantAppService { get; set; }
public IFormsAppService FormsAppService { get; set; }
public IUsersAppService UsersAppService { get; set; }
private readonly IUnitOfWorkManager UnitOfWorkManager;
public RegisterModel(IAbpTenantAppService abpTenantAppService, IFormsAppService formsAppService, IUsersAppService usersAppService, IUnitOfWorkManager unitOfWorkManager)
{
AbpTenantAppService = abpTenantAppService;
FormsAppService = formsAppService;
UsersAppService = usersAppService;
UnitOfWorkManager = unitOfWorkManager;
}
[BindProperty(SupportsGet = true)]
public string? ReturnUrl { get; set; }
[BindProperty(SupportsGet = true)]
public string? ReturnUrlHash { get; set; }
[BindProperty(SupportsGet = true)]
public Guid TenantId { get; set; }
[BindProperty]
public PostInput Input { get; set; }
[BindProperty]
public List<Field> Fields { get; set; }
[BindProperty]
public List<QuestionDto> QuestionDtos { get; set; }
private async Task CreateExtraFields()
{
var tenant = await AbpTenantAppService.FindTenantByIdAsync(TenantId);
if (tenant.TenantId != null)
{
var form = await FormsAppService.GetRegistrationFormAsync(TenantId);
QuestionDtos = form.Questions;
}
Fields = new List<Field>();
foreach (var item in QuestionDtos)
{
var choices = new List<SelectListItem>();
foreach (var choice in item.Choices)
{
choices.Add(new SelectListItem()
{
Text = choice.Value,
Value = choice.Value
});
}
Field field = new Field
{
Index = item.Index,
Title = item.Title,
IsRequired = item.IsRequired,
HasOtherOption = item.HasOtherOption,
QuestionType = item.QuestionType,
Answer = null,
Choices = choices,
Answers = null
};
Fields.Add(field);
}
}
[BindProperty(SupportsGet = true)]
public bool IsExternalLogin { get; set; }
public bool LocalLoginDisabled { get; set; }
public bool UseCaptcha { get; set; }
public virtual async Task<IActionResult> OnGetAsync()
{
//await ValidateForm();
var localLoginResult = await CheckLocalLoginAsync();
if (localLoginResult != null)
{
LocalLoginDisabled = true;
return localLoginResult;
}
await CheckSelfRegistrationAsync();
await TrySetEmailAsync();
await SetUseCaptchaAsync();
await CreateExtraFields();
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
{
var localLoginResult = await CheckLocalLoginAsync();
if (localLoginResult != null)
{
LocalLoginDisabled = true;
return localLoginResult;
}
user = await RegisterLocalUserAsync();
}
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));
return Page();
}
}
[UnitOfWork]
protected virtual async Task<IdentityUser> RegisterLocalUserAsync()
{
using (var unitOfWork = UnitOfWorkManager.Begin())
{
ValidateModel();
var captchaResponse = string.Empty;
if (UseCaptcha)
{
captchaResponse = HttpContext.Request.Form[RecaptchaValidatorBase.RecaptchaResponseKey];
}
RegisterDto registerDto = new RegisterDto()
{
AppName = "MVC",
EmailAddress = Input.EmailAddress,
Password = Input.Password,
UserName = Input.UserName,
ReturnUrl = ReturnUrl,
ReturnUrlHash = ReturnUrlHash,
CaptchaResponse = captchaResponse
};
foreach (var item in Fields)
{
if (item.Answers != null)
{
string result = "{";
foreach (var answer in item.Answers)
{
result += '"' + answer + '"';
if (!(answer == item.Answers.LastOrDefault()))
{
result += ",";
}
}
result += "}";
item.Answer = result;
}
registerDto.SetProperty(item.Title, item.Answer);
}
var userDto = await AccountAppService.RegisterAsync(registerDto);
RegisterUser registerUser = new RegisterUser(userDto.Id, Input.UserName, Input.EmailAddress, TenantId, userDto.CreationTime, "Patient", Input.Password);
foreach (var key in Fields)
{
switch (key.Title)
{
case "Name":
registerUser.first_name = key.Answer;
break;
case "Surname":
registerUser.last_name = key.Answer;
break;
case "DOB":
registerUser.dob = DateTime.Parse(key.Answer);
break;
case "Gender":
registerUser.gender = key.Answer;
break;
default:
break;
}
}
await UsersAppService.RegisterUser(registerUser);
return await UserManager.GetByIdAsync(userDto.Id);
}
}
private async Task<bool> ValidateForm()
{
return true;
}
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; }
}
public class Field
{
public int Index { get; set; }
public string? Title { get; set; }
public bool IsRequired { get; set; }
public bool HasOtherOption { get; set; }
public QuestionTypes QuestionType { get; set; }
public string? Answer { get; set; }
public List<string>? Answers { get; set; }
public List<SelectListItem>? Choices { get; set; }
}
}
Here the variable "Fields" holds the details of those extra input fields which I am fetching from the database. As you can see those fields would not appear after clicking on Register, can you suggest what can I do so that the fields won't disappear.
I am working on the Auth Server project (independent). I have a requirement where I want to put some extra input fields on the Registration page of auth server. I'd collect the values of those extra input fields and will store those values in my other database table (separate from the ones provided by ABP). I am even able to carry out the whole process and am successfully able to store the data in the database without altering the existing configuration. I am fetching the details of those input fields from my database and storing them in a variable in the Register.cshtml.cs file. And I am using that variable to display those input fields on UI.
Now, here the problem is, that if I have any kind of a validation error (username already taken for example), and if I try to submit at this point, the application will pop out the validation error, saying this username is already taken, which is fine. But all my input fields get disappeared as soon as there is some validation error. I think this is happening because the class is losing all of it's values as soon as there is any validation error and hence it resets all the variables of the class and hence my variable (which stores the input field details), also gets reset and therefore loses all the details and it doesn't appear on the UI.
Is there a way to keep the value of that variable held during the entire time? Any kind of annotation or something? Please suggest.
I have a requirement where I am trying to call the FormAppService from the Forms module in my AuthServe. I have to get the form details from the FormId that I will provide. I have done all the configuration. Added the FormHttpApiClientModule in my AuthServer project's module.cs file. I have created an instance of the IFormAppService interface in the Register.cshtml.cs file. And using it I am calling the GetAsync method of the interface which will fetch the form data with the Id parameter. But when the GetAsync method is called it throws the following exception.
NullReferenceException: Object reference not set to an instance of an object. Volo.Abp.Http.Client.ClientProxying.ClientProxyApiDescriptionFinder.Initialize()
DependencyResolutionException: An exception was thrown while invoking the constructor 'Void .ctor(Volo.Abp.VirtualFileSystem.IVirtualFileProvider, Volo.Abp.Json.IJsonSerializer)' on type 'ClientProxyApiDescriptionFinder'. Autofac.Core.Activators.Reflection.BoundConstructor.Instantiate()
DependencyResolutionException: An exception was thrown while activating λ:Volo.Abp.Http.Client.ClientProxying.IClientProxyApiDescriptionFinder -> Volo.Abp.Http.Client.ClientProxying.ClientProxyApiDescriptionFinder. Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action<ResolveRequestContext> next)
DependencyResolutionException: An exception was thrown while activating λ:Volo.Abp.Http.Client.ClientProxying.IClientProxyApiDescriptionFinder -> Volo.Abp.Http.Client.ClientProxying.ClientProxyApiDescriptionFinder. Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action<ResolveRequestContext> next) Autofac.Core.Resolving.Middleware.SharingMiddleware+<>c__DisplayClass5_0.<Execute>b__0() Autofac.Core.Lifetime.LifetimeScope.CreateSharedInstance(Guid id, Func<object> creator) Autofac.Core.Lifetime.LifetimeScope.CreateSharedInstance(Guid primaryId, Nullable<Guid> qualifyingId, Func<object> creator) Autofac.Core.Resolving.Middleware.SharingMiddleware.Execute(ResolveRequestContext context, Action<ResolveRequestContext> next) Autofac.Core.Resolving.Middleware.CircularDependencyDetectorMiddleware.Execute(ResolveRequestContext context, Action<ResolveRequestContext> next) Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ResolveRequest request) Autofac.Core.Resolving.ResolveOperation.ExecuteOperation(ResolveRequest request) Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable<Parameter> parameters, out object instance) Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable<Parameter> parameters) System.Lazy<T>.ViaFactory(LazyThreadSafetyMode mode) System.Lazy<T>.ExecutionAndPublication(LazyHelper executionAndPublication, bool useDefaultConstructor) System.Lazy<T>.CreateValue() Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) Volo.Abp.DependencyInjection.AbpLazyServiceProvider.LazyGetRequiredService<T>() Volo.Abp.Http.Client.ClientProxying.ClientProxyBase<TService>.get_ClientProxyApiDescriptionFinder() Volo.Abp.Http.Client.ClientProxying.ClientProxyBase<TService>.BuildHttpProxyClientProxyContext(string methodName, ClientProxyRequestTypeValue arguments) Volo.Abp.Http.Client.ClientProxying.ClientProxyBase<TService>.RequestAsync<T>(string methodName, ClientProxyRequestTypeValue arguments) Volo.Forms.Forms.ClientProxies.FormClientProxy.GetAsync(Guid id) in FormClientProxy.Generated.cs + return await RequestAsync<FormWithDetailsDto>(nameof(GetAsync), new ClientProxyRequestTypeValue G1.health.AuthServer.Pages.Account.RegisterModel.CreateExtraFields() in Register.cshtml.cs + var form = await FormAppService.GetAsync((Guid)tenant.TenantId); G1.health.AuthServer.Pages.Account.RegisterModel.OnGetAsync() in Register.cshtml.cs + await CreateExtraFields(); Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory+GenericTaskHandlerMethod.Convert<T>(object taskAsObject) Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory+GenericTaskHandlerMethod.Execute(object receiver, object[] arguments) Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeHandlerMethodAsync() Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeNextPageFilterAsync() Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Rethrow(PageHandlerExecutedContext context) Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeInnerFilterAsync() Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ExceptionContextSealed context) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker) Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) Volo.Abp.AspNetCore.Uow.AbpUnitOfWorkMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Volo.Abp.AspNetCore.Serilog.AbpSerilogMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Volo.Abp.AspNetCore.MultiTenancy.MultiTenancyMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Microsoft.AspNetCore.Builder.ApplicationBuilderAbpOpenIddictMiddlewareExtension+<>c__DisplayClass0_0+<<UseAbpOpenIddictValidation>b__0>d.MoveNext() Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) Prometheus.HttpMetrics.HttpRequestDurationMiddleware.Invoke(HttpContext context) Prometheus.HttpMetrics.HttpRequestCountMiddleware.Invoke(HttpContext context) Prometheus.HttpMetrics.HttpInProgressMiddleware.Invoke(HttpContext context) Volo.Abp.AspNetCore.Security.AbpSecurityHeadersMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Volo.Abp.AspNetCore.Tracing.AbpCorrelationIdMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.RequestLocalization.AbpRequestLocalizationMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
It was working day before yesterday, but all of a sudden it's throwing the above error. I am not sure, what am I missing here. Can you suggest me what can be the possible solution to resolve this?