Open Closed

Extension property in Identity Users not working in Azure #6195


User avatar
0
ccernat created
  • ABP Framework version: v7.4.2
  • UI Type: Blazor Server
  • Database System: EF Core (SQL Server, Oracle, MySQL, PostgreSQL, etc..)
  • Tiered (for MVC) or Auth Server Separated (for Angular): no
  • Exception message and full stack trace:
  • 2023-11-20 09:24:03.726 +00:00 [WRN] Unhandled exception rendering component: Object reference not set to an instance of an object. System.NullReferenceException: Object reference not set to an instance of an object. at Volo.Abp.AspNetCore.Components.Server.Extensibility.BlazorServerLookupApiRequestService.SendAsync(String url) at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty2.GetLookupItemsAsync(String filter) at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty2.SearchFilterChangedAsync(String filter) at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty2.OnAfterRenderAsync(Boolean firstRender) 2023-11-20 09:24:03.726 +00:00 [ERR] Unhandled exception in circuit 'gVmyUOQWHKurypwoO3OdZidqK0d9rq7lQE3WxUePTVU'. System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.) ---> System.NullReferenceException: Object reference not set to an instance of an object. at Volo.Abp.AspNetCore.Components.Server.Extensibility.BlazorServerLookupApiRequestService.SendAsync(String url) at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty2.GetLookupItemsAsync(String filter) at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty2.SearchFilterChangedAsync(String filter) at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty2.OnAfterRenderAsync(Boolean firstRender) --- End of inner exception stack trace ---
  • Steps to reproduce the issue:

I extended the existing IdentityUser with the extension system, and also had it mapped to a different column using ef core mapping, which is working fine locally.

Normal behavior locally when adding or editing a user:

After deploying to Azure, is not working anymore and I get a Blazor error when trying to add or edit a user:

If I go to /api/providers I get a normal response:

What am I doing wrong? Please note that all other aspects of the app deployed to AZ are working as intended.


19 Answer(s)
  • User Avatar
    0
    Anjali_Musmade created
    Support Team Support Team Member

    Hi ccernat,

    Can you please check your deployed database to see if the values for ProviderId are present or not?

  • User Avatar
    0
    ccernat created

    Hello!

    All good there. As I said, if I access the endpoint /api/providers on Azure, I get the correct response, with the providers list, as shown in the screen in the 1st post.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Please share full error logs. Thanks

    Include Api and balzor websites.

    liming.ma@volosoft.com

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Please add the MyBlazorServerLookupApiRequestService to your blazor project and try again. The error logs will show the reason.

    After the above test, you can add RemoteServices to your appsettins.json

      "RemoteServices": {
        "Default": {
          "BaseUrl": "https://your-real-url-dev.azurewebsites.net/"
        }
      },
    

    Thanks.

    using System;
    using System.Globalization;
    using System.Net.Http;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Components;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Logging;
    using Volo.Abp;
    using Volo.Abp.AspNetCore.Components.Web.Extensibility;
    using Volo.Abp.DependencyInjection;
    using Volo.Abp.Http.Client;
    using Volo.Abp.Http.Client.Authentication;
    using Volo.Abp.MultiTenancy;
    
    namespace Metro.Blazor;
    
    [Dependency(ReplaceServices = true)]
    public class MyBlazorServerLookupApiRequestService : ILookupApiRequestService, ITransientDependency
    {
        public IHttpClientFactory HttpClientFactory { get; }
        public IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; }
        public IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider { get; }
        public ICurrentTenant CurrentTenant { get; }
        public IHttpContextAccessor HttpContextAccessor { get; }
        public NavigationManager NavigationManager { get; }
    
        public ILogger<MyBlazorServerLookupApiRequestService> Logger { get; }
    
        public MyBlazorServerLookupApiRequestService(IHttpClientFactory httpClientFactory,
            IRemoteServiceHttpClientAuthenticator httpClientAuthenticator,
            ICurrentTenant currentTenant,
            IHttpContextAccessor httpContextAccessor,
            NavigationManager navigationManager,
            IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider,
            ILogger<MyBlazorServerLookupApiRequestService> logger)
        {
            HttpClientFactory = httpClientFactory;
            HttpClientAuthenticator = httpClientAuthenticator;
            CurrentTenant = currentTenant;
            HttpContextAccessor = httpContextAccessor;
            NavigationManager = navigationManager;
            RemoteServiceConfigurationProvider = remoteServiceConfigurationProvider;
            Logger = logger;
        }
    
        public async Task<string> SendAsync(string url)
        {
            Logger.LogError("SendAsync: {url}", url);
    
            var client = HttpClientFactory.CreateClient();
            var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
    
            var uri = new Uri(url, UriKind.RelativeOrAbsolute);
            if (!uri.IsAbsoluteUri)
            {
                Logger.LogError("SendAsync: {url} is not absolute uri", url);
    
                var baseUrl = string.Empty;
                try
                {
                    //Blazor tiered -- mode
                    var remoteServiceConfig = await RemoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync("Default");
                    baseUrl = remoteServiceConfig.BaseUrl;
    
                    Logger.LogError("Blazor tiered -- mode: {baseUrl}", baseUrl);
    
                    client.BaseAddress = new Uri(baseUrl);
                    AddHeaders(requestMessage);
                    await HttpClientAuthenticator.Authenticate(new RemoteServiceHttpClientAuthenticateContext(client,
                        requestMessage, new RemoteServiceConfiguration(baseUrl), string.Empty));
                }
                catch (AbpException e) // Blazor-Server mode.
                {
                    Logger.LogError(e, "AbpException: {message}", e.Message);
    
                    baseUrl = NavigationManager.BaseUri;
    
                    Logger.LogError("AbpException Blazor tiered -- mode: {baseUrl}", baseUrl);
    
                    client.BaseAddress = new Uri(baseUrl);
                    foreach (var header in HttpContextAccessor.HttpContext!.Request.Headers)
                    {
                        requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
                    }
                }
            }
    
            var response = await client.SendAsync(requestMessage);
            return await response.Content.ReadAsStringAsync();
        }
    
        protected virtual void AddHeaders(HttpRequestMessage requestMessage)
        {
            if (CurrentTenant.Id.HasValue)
            {
                requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString());
            }
    
            var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name;
            if (!currentCulture.IsNullOrEmpty())
            {
                requestMessage.Headers.AcceptLanguage.Add(new(currentCulture));
            }
        }
    }
    
    
    System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.)
     ---> System.NullReferenceException: Object reference not set to an instance of an object.
       at Volo.Abp.AspNetCore.Components.Server.Extensibility.BlazorServerLookupApiRequestService.SendAsync(String url)
       at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty`2.GetLookupItemsAsync(String filter)
       at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty`2.SearchFilterChangedAsync(String filter)
       at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty`2.OnAfterRenderAsync(Boolean firstRender)
       --- End of inner exception stack trace ---
    
  • User Avatar
    0
    ccernat created

    Hi,

    The original error disappeared, but now I have this:

    2023-11-22 07:14:32.122 +02:00 [WRN] Unhandled exception rendering component: '<' is an invalid start of a value. LineNumber: 1 | BytePositionInLine: 0. System.Text.Json.JsonReaderException: '<' is an invalid start of a value. LineNumber: 1 | BytePositionInLine: 0. at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan1 bytes) at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte marker) at System.Text.Json.Utf8JsonReader.ReadFirstToken(Byte first) at System.Text.Json.Utf8JsonReader.ReadSingleSegment() at System.Text.Json.Utf8JsonReader.Read() at System.Text.Json.JsonDocument.Parse(ReadOnlySpan1 utf8JsonSpan, JsonReaderOptions readerOptions, MetadataDb& database, StackRowStack& stack) at System.Text.Json.JsonDocument.Parse(ReadOnlyMemory1 utf8Json, JsonReaderOptions readerOptions, Byte[] extraRentedArrayPoolBytes, PooledByteBufferWriter extraPooledByteBufferWriter) at System.Text.Json.JsonDocument.Parse(ReadOnlyMemory1 json, JsonDocumentOptions options) at System.Text.Json.JsonDocument.Parse(String json, JsonDocumentOptions options) at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty2.GetLookupItemsAsync(String filter) at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty2.SearchFilterChangedAsync(String filter) at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty2.OnAfterRenderAsync(Boolean firstRender) at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState) 2023-11-22 07:14:32.129 +02:00 [ERR] Unhandled exception in circuit 'PzKxz14If1PFA-nNOPshZvR2VREDcT6b8hBgLIBgji0'. System.Text.Json.JsonReaderException: '<' is an invalid start of a value. LineNumber: 1 | BytePositionInLine: 0. at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan1 bytes) at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte marker) at System.Text.Json.Utf8JsonReader.ReadFirstToken(Byte first) at System.Text.Json.Utf8JsonReader.ReadSingleSegment() at System.Text.Json.Utf8JsonReader.Read() at System.Text.Json.JsonDocument.Parse(ReadOnlySpan1 utf8JsonSpan, JsonReaderOptions readerOptions, MetadataDb& database, StackRowStack& stack) at System.Text.Json.JsonDocument.Parse(ReadOnlyMemory1 utf8Json, JsonReaderOptions readerOptions, Byte[] extraRentedArrayPoolBytes, PooledByteBufferWriter extraPooledByteBufferWriter) at System.Text.Json.JsonDocument.Parse(ReadOnlyMemory1 json, JsonDocumentOptions options) at System.Text.Json.JsonDocument.Parse(String json, JsonDocumentOptions options) at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty2.GetLookupItemsAsync(String filter) at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty2.SearchFilterChangedAsync(String filter) at Volo.Abp.BlazoriseUI.Components.ObjectExtending.LookupExtensionProperty2.OnAfterRenderAsync(Boolean firstRender) at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState) 2023-11-22 07:14:32.133 +02:00 [INF] Executed endpoint '/_blazor'

    This is because it's returning the login page, but I am logged in and the controller is decorated with the Authorized for Admin role. I wouldn't want to allow anonymous on that endpoint.

    PS: Shouldn't the app settings related to RemoteServices:Default:BaseUrl be generated with the Blazor Server template from ABP Suite?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Let me check it on the azure website.

    And share your logs.txt again. Thanks.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Please enable the WebSocket feature in your Azure server.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Let;s check what is the value of responseString

    var responseString = await response.Content.ReadAsStringAsync();
    Logger.LogInformation("Response: {0}", responseString);
    return responseString;
    
    [Dependency(ReplaceServices = true)]
    public class MyBlazorServerLookupApiRequestService : ILookupApiRequestService, ITransientDependency
    {
        public IHttpClientFactory HttpClientFactory { get; }
        public IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; }
        public IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider { get; }
        public ICurrentTenant CurrentTenant { get; }
        public IHttpContextAccessor HttpContextAccessor { get; }
        public NavigationManager NavigationManager { get; }
    
        public ILogger<MyBlazorServerLookupApiRequestService> Logger { get; }
    
        public MyBlazorServerLookupApiRequestService(IHttpClientFactory httpClientFactory,
            IRemoteServiceHttpClientAuthenticator httpClientAuthenticator,
            ICurrentTenant currentTenant,
            IHttpContextAccessor httpContextAccessor,
            NavigationManager navigationManager,
            IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider,
            ILogger<MyBlazorServerLookupApiRequestService> logger)
        {
            HttpClientFactory = httpClientFactory;
            HttpClientAuthenticator = httpClientAuthenticator;
            CurrentTenant = currentTenant;
            HttpContextAccessor = httpContextAccessor;
            NavigationManager = navigationManager;
            RemoteServiceConfigurationProvider = remoteServiceConfigurationProvider;
            Logger = logger;
        }
    
        public async Task<string> SendAsync(string url)
        {
            var client = HttpClientFactory.CreateClient();
            var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
    
            var uri = new Uri(url, UriKind.RelativeOrAbsolute);
            if (!uri.IsAbsoluteUri)
            {
                var remoteServiceConfig = await RemoteServiceConfigurationProvider.GetConfigurationOrDefaultOrNullAsync("Default");
                if (remoteServiceConfig != null)
                {
                    // Blazor tiered mode
                    var baseUrl = remoteServiceConfig.BaseUrl;
                    client.BaseAddress = new Uri(baseUrl);
                    AddHeaders(requestMessage);
                    await HttpClientAuthenticator.Authenticate(new RemoteServiceHttpClientAuthenticateContext(client, requestMessage, new RemoteServiceConfiguration(baseUrl), string.Empty));
                }
                else
                {
                    // Blazor server  mode
                    client.BaseAddress = new Uri(NavigationManager.BaseUri);
                    foreach (var header in HttpContextAccessor.HttpContext!.Request.Headers)
                    {
                        requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
                    }
                }
            }
    
            var response = await client.SendAsync(requestMessage);
    
            var responseString = await response.Content.ReadAsStringAsync();
    
            Logger.LogInformation("Response: {0}", responseString);
    
            return responseString;
        }
    
        protected virtual void AddHeaders(HttpRequestMessage requestMessage)
        {
            if (CurrentTenant.Id.HasValue)
            {
                requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString());
            }
    
            var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name;
            if (!currentCulture.IsNullOrEmpty())
            {
                requestMessage.Headers.AcceptLanguage.Add(new(currentCulture));
            }
        }
    }
    
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Please add these code to output the headers.

    We have to attach the cookies to call the endpoint.

    If there is no cookies, the HTML of login page will show up.

    // Blazor server mode
    client.BaseAddress = new Uri(NavigationManager.BaseUri);
    foreach (var header in HttpContextAccessor.HttpContext!.Request.Headers)
    {
        Logger.LogInformation("Header: {0} = {1}", header.Key, header.Value);
        requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
    }
    
  • User Avatar
    0
    ccernat created

    Replied on email with the logs.

    Tks.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you set the MinimumLevel to Debug?

    Thanks.

    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Debug()
        .Enrich.FromLogContext()
        .WriteTo.Async(c => c.File("Logs/logs.txt"))
        .WriteTo.Async(c => c.Console())
        .CreateLogger();
    
  • User Avatar
    0
    ccernat created

    Done. Sent by email.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Thank you!

    We have to remove the Accept-Encoding header.

    The solution is:

    
    // Blazor server mode
    client.BaseAddress = new Uri(NavigationManager.BaseUri);
    foreach (var header in HttpContextAccessor.HttpContext!.Request.Headers.Where(x => x.Key != "Accept-Encoding"))
    {
        requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
    }
    
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    https://github.com/abpframework/abp/pull/18226

  • User Avatar
    0
    ccernat created

    Hi,

    It's working correctly now but only returns 10 items.

    Where can I change the paging? Or to return me all the items from the controller?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    This feature doesn't support paging now.

  • User Avatar
    0
    ccernat created

    But how can I return all items? I don't want paging. I want all items. It returns only 1st 10 items.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    You can add a new method to app service to get all items.

    Or set the MaxResultCount of GetProvidersInput to int.MaxValue.

    so add a new method will be better.

  • User Avatar
    0
    ccernat created

    Tks. Solved!

Made with ❤️ on ABP v9.1.0-preview. Updated on November 19, 2024, 12:56