Activities of "ageiter"

You can call the await InvokeAsync(StateHasChanged) after changing the SelectedTenantId. Ensure the input has set the correct value.

The problem was that the DOM had not yet been updated at that moment. I solved it as follows:

<form method="post" action="Account/ImpersonateTenant" id="impersonateTenantForm">
    <input type="hidden" name="TenantId" value="@SelectedTenantId" />
    <input type="hidden" name="TenantUserName" value="admin" />
</form>
private Guid SelectedTenantId { get; set; }
private bool ShouldSubmitImpersonateTenantForm { get; set; } = false;
        
protected override async Task OnAfterRenderAsync(bool firstRender)
{
    // Submit the impersonateTenantForm after setting the tenant ID
    if (ShouldSubmitImpersonateTenantForm)
    {
        ShouldSubmitImpersonateTenantForm = false;
        await JS.InvokeVoidAsync("submitForm", "impersonateTenantForm");
    }
}
        
private async Task OnImpersonateTenantClick(Guid tenantId)
{
    SelectedTenantId = tenantId;
    ShouldSubmitImpersonateTenantForm = true;

    await InvokeAsync(StateHasChanged);
}
function submitForm(formName) {
    var form = document.getElementById(formName);
    form.submit();
}

You can call the await InvokeAsync(StateHasChanged) after changing the SelectedTenantId. Ensure the input has set the correct value.

I tried that too, but it didn't work. I thought it should work...

What can you tell me about the ReturnUrl?

I found another solution by creating a form around each button.

One more question: what is the purpose of the ReturnUrl? Is it to go to a specific page on the tenant or to return to a specific page when returning to the host?

Neither seems to work.

I found the problem. It works for me with hard-coded values. The problem is that SelectedTenantId and SelectedTenantUserName are set too late and are not included when the form is submitted.

I guess I'll have to write it in via JavaScript, or do you have a better solution?

I just sent you the log file to your email.

Unfortunately, I haven't been able to get it to work yet. I tried three different variations. With the first two, I get the error message: “There is no user with username: admin!” But this user does exist (it also works when I use impersonation in the other way).

I don't see any error messages or other indications in the log file.

The third option is the one suggested above by the AI bot. But there I get a 404 error.

This is the code:

<form method="post" action="Account/ImpersonateTenant" id="ImpersonationForm1">
    <input type="hidden" name="TenantId" value="@SelectedTenantId" />
    <input type="hidden" name="TenantUserName" value="@SelectedTenantUserName" />
</form>

<form method="post" data-ajaxForm="false" action="Account/ImpersonateTenant" id="ImpersonationForm2">
    <AntiforgeryToken />
    <input type="hidden" name="ReturntId" value="@SelectedTenantId" />
    <input type="hidden" name="TenantUserName" value="@SelectedTenantUserName" />
    <input type="hidden" name="ReturnUrl" value="" />
</form>
// Impersonation variant 1
private async Task SubmitImpersonationForm1(Guid tenantId)
{
    Logger.Log(LogLevel.Information, "Start impersonation variant 1");

    SelectedTenantId = tenantId.ToString();
    SelectedTenantUserName = "admin";

    await JSRuntime.InvokeVoidAsync("submitForm", "ImpersonationForm1");
}

// Impersonation variant 2
private async Task SubmitImpersonationForm2(Guid tenantId)
{
    Logger.Log(LogLevel.Information, "Start impersonation variant 2");

    SelectedTenantId = tenantId.ToString();
    SelectedTenantUserName = "admin";

    var tokens = Antiforgery.GetAndStoreTokens(HttpContextAccessor.HttpContext);
    var requestToken = tokens.RequestToken;

    await JSRuntime.InvokeVoidAsync("submitFormWithAntiforgeryToken", "ImpersonationForm2", $"/Account/ImpersonateTenant", requestToken);
}

// Impersonation variant 3
private async Task SubmitImpersonationForm3(Guid tenantId)
{
    Logger.Log(LogLevel.Information, "Start impersonation variant 3");

    //var response = await Http.PostAsJsonAsync("/api/account/impersonation/tenant", new { tenantId });
    var response = await Http.PostAsJsonAsync("https://localhost:44367/api/account/impersonation/tenant", new { tenantId });
    if (response.IsSuccessStatusCode)
    {
        //var result = await response.Content.ReadFromJsonAsync<ImpersonateResultDto>();
        //NavigationManager.NavigateTo(result.ImpersonationUrl, forceLoad: true);
    }
}
function submitForm(formName) {
        var form = document.getElementById(formName);
        form.submit();
}

function submitFormWithAntiforgeryToken(formName, uri, requestToken) {
    var form = document.getElementById(formName);

    // Check if the antiforgery token is present in the form, if the token is not present, create a new hidden input field for the token
    var tokenInput = form.querySelector('input[name=__RequestVerificationToken]');
    if (!tokenInput) {
        {
            tokenInput = document.createElement('input');
            tokenInput.type = 'hidden';
            tokenInput.name = '__RequestVerificationToken';
            form.appendChild(tokenInput);
        }
    }

    // Set the value of the token
    tokenInput.value = requestToken;

    // Update the form's action with the new URI and submit the form
    form.action = uri;
    form.submit();
}

Any ideas?

I mean something like this:

await AccountAppService.ImpersonateTenantAsync()

Is this possible?

Is there no way to call up a corresponding service method from the SaaS module directly from my AppService?

We frequently use tenant impersonation via the tenant list. However, we want to call it directly via our dashboard, as we have a client list there and want to avoid the detour via your tenant list in the SaaS module.

Since the source for this is not public, I have unfortunately not been able to figure out how to implement this. Can you tell me how I should do this?

I want exactly the same behavior. Click on a link on the tenant, then the pop-up should open to enter the username, etc.

Thanks, Adrian

Showing 11 to 20 of 312 entries
Learn More, Pay Less
33% OFF
All Trainings!
Get Your Deal
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.0.0-preview. Updated on September 12, 2025, 10:20