Activities of "maliming"

hi

You can test 1 or 2.

Thanks.

  1. You can try to disable the DynamicClaims.
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
    options.IsDynamicClaimsEnabled = false;
});
  1. You can use the latest middleware code.
- app.UseDynamicClaims();
+ app.UseMiddleware<MyAbpDynamicClaimsMiddleware>();
public class MyAbpDynamicClaimsMiddleware : AbpMiddlewareBase, ITransientDependency
{
    public async override Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        if (context.User.Identity?.IsAuthenticated == true)
        {
            if (context.RequestServices.GetRequiredService<IOptions<AbpClaimsPrincipalFactoryOptions>>().Value.IsDynamicClaimsEnabled)
            {
                var authenticateResultFeature = context.Features.Get<IAuthenticateResultFeature>();
                var authenticationType = authenticateResultFeature?.AuthenticateResult?.Ticket?.AuthenticationScheme ?? context.User.Identity.AuthenticationType;

                if (authenticateResultFeature != null && !authenticationType.IsNullOrWhiteSpace())
                {
                    var abpClaimsPrincipalFactory = context.RequestServices.GetRequiredService<IAbpClaimsPrincipalFactory>();
                    var user = await abpClaimsPrincipalFactory.CreateDynamicAsync(context.User);

                    authenticateResultFeature.AuthenticateResult = AuthenticateResult.Success(new AuthenticationTicket(
                        user,
                        authenticateResultFeature?.AuthenticateResult?.Properties,
                        authenticationType));
                }

                if (context.User.Identity?.IsAuthenticated == false)
                {
                    var authenticationSchemeProvider = context.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>();
                    if (!authenticationType.IsNullOrWhiteSpace())
                    {
                        var authenticationScheme = await authenticationSchemeProvider.GetSchemeAsync(authenticationType);
                        if (authenticationScheme != null && typeof(IAuthenticationSignOutHandler).IsAssignableFrom(authenticationScheme.HandlerType))
                        {
                            await context.SignOutAsync(authenticationScheme.Name);
                        }
                    }
                }
            }
        }

        await next(context);
    }
}

hi

Can you share test project to reproduce?

liming.ma@volosoft.com

Thanks.

hi

Can you share full debug logs(include HTTP request/response and EF Core)?

liming.ma@volosoft.com

https://abp.io/support/questions/8622/How-to-enable-Debug-logs-for-troubleshoot-problems

Thanks.

hi

Why does your api project use Identity Server and OpenID Connect at the same time?

Removing Identity Server will work.

Answer

hi

Can you share your full code?

I will download and test it.

Thanks

liming.ma@volosoft.com

Great, I fixed in 9.0.

You can remove the patch code after upgrading to 9.0

hi

The fix code:

AbpSolution1HttpApiHostModule:

public override void ConfigureServices(ServiceConfigurationContext context)
{


    PostConfigure<MvcOptions>(options =>
    {
        options.ModelBinderProviders.RemoveAll(x => x.GetType() == typeof(AbpRemoteStreamContentModelBinderProvider));
        options.ModelBinderProviders.Insert(2, new MyAbpRemoteStreamContentModelBinderProvider());
    });
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Volo.Abp.AspNetCore.Mvc.ContentFormatters;
using Volo.Abp.Content;

namespace AbpSolution1;

public class MyAbpRemoteStreamContentModelBinderProvider : IModelBinderProvider
{
    public IModelBinder? GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (context.Metadata.ModelType == typeof(RemoteStreamContent) ||
            typeof(IEnumerable<RemoteStreamContent>).IsAssignableFrom(context.Metadata.ModelType))
        {
            return new MyAbpRemoteStreamContentModelBinder<RemoteStreamContent>();
        }

        if (context.Metadata.ModelType == typeof(IRemoteStreamContent) ||
            typeof(IEnumerable<IRemoteStreamContent>).IsAssignableFrom(context.Metadata.ModelType))
        {
            return new MyAbpRemoteStreamContentModelBinder<IRemoteStreamContent>();
        }

        return null;
    }
}

public class MyAbpRemoteStreamContentModelBinder<TRemoteStreamContent> : IModelBinder
    where TRemoteStreamContent: class, IRemoteStreamContent
{
    public async Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        var postedFiles = GetCompatibleCollection<TRemoteStreamContent>(bindingContext);

        // If we're at the top level, then use the FieldName (parameter or property name).
        // This handles the fact that there will be nothing in the ValueProviders for this parameter
        // and so we'll do the right thing even though we 'fell-back' to the empty prefix.
        var modelName = bindingContext.IsTopLevelObject
            ? bindingContext.BinderModelName ?? bindingContext.FieldName
            : bindingContext.ModelName;

        await GetFormFilesAsync(modelName, bindingContext, postedFiles);

        // If ParameterBinder incorrectly overrode ModelName, fall back to OriginalModelName prefix. Comparisons
        // are tedious because e.g. top-level parameter or property is named Blah and it contains a BlahBlah
        // property. OriginalModelName may be null in tests.
        if (postedFiles.Count == 0 &&
            bindingContext.OriginalModelName != null &&
            !string.Equals(modelName, bindingContext.OriginalModelName, StringComparison.Ordinal) &&
            !modelName.StartsWith(bindingContext.OriginalModelName + "[", StringComparison.Ordinal) &&
            !modelName.StartsWith(bindingContext.OriginalModelName + ".", StringComparison.Ordinal))
        {
            modelName = ModelNames.CreatePropertyModelName(bindingContext.OriginalModelName, modelName);
            await GetFormFilesAsync(modelName, bindingContext, postedFiles);
        }

        object value;
        if (bindingContext.ModelType == typeof(TRemoteStreamContent))
        {
            if (postedFiles.Count == 0)
            {
                // Silently fail if the named file does not exist in the request.
                return;
            }

            value = postedFiles.First();
        }
        else
        {
            if (postedFiles.Count == 0 && !bindingContext.IsTopLevelObject)
            {
                // Silently fail if no files match. Will bind to an empty collection (treat empty as a success
                // case and not reach here) if binding to a top-level object.
                return;
            }

            // Perform any final type mangling needed.
            var modelType = bindingContext.ModelType;
            if (modelType == typeof(TRemoteStreamContent[]))
            {
                value = postedFiles.ToArray();
            }
            else
            {
                value = postedFiles;
            }
        }

        // We need to add a ValidationState entry because the modelName might be non-standard. Otherwise
        // the entry we create in model state might not be marked as valid.
        bindingContext.ValidationState.Add(value, new ValidationStateEntry()
        {
            Key = modelName,
        });

        bindingContext.ModelState.SetModelValue(
            modelName,
            rawValue: null,
            attemptedValue: null);

        bindingContext.Result = ModelBindingResult.Success(value);
    }

    private async Task GetFormFilesAsync(
        string modelName,
        ModelBindingContext bindingContext,
        ICollection<TRemoteStreamContent> postedFiles)
    {
        var request = bindingContext.HttpContext.Request;
        if (request.HasFormContentType)
        {
            var form = await request.ReadFormAsync();

            var useMemoryStream = form.Files.Count > 1;
            foreach (var file in form.Files)
            {
                // If there is an <input type="file" ... /> in the form and is left blank.
                if (file.Length == 0 && string.IsNullOrEmpty(file.FileName))
                {
                    continue;
                }

                if (file.Name.Equals(modelName, StringComparison.OrdinalIgnoreCase))
                {
                    if (useMemoryStream)
                    {
                        var memoryStream = new MemoryStream();
                        await file.OpenReadStream().CopyToAsync(memoryStream);
                        memoryStream.Position = 0;
                        postedFiles.Add(new RemoteStreamContent(memoryStream, file.FileName, file.ContentType, file.Length, disposeStream: false).As<TRemoteStreamContent>());
                        bindingContext.HttpContext.Response.OnCompleted(async () =>
                        {
                            await memoryStream.DisposeAsync();
                        });
                    }
                    else
                    {
                        postedFiles.Add(new RemoteStreamContent(file.OpenReadStream(), file.FileName, file.ContentType, file.Length, disposeStream: false).As<TRemoteStreamContent>());
                    }
                }
            }
        }
        else if (bindingContext.IsTopLevelObject)
        {
            postedFiles.Add(new RemoteStreamContent(request.Body, null, request.ContentType, request.ContentLength).As<TRemoteStreamContent>());
        }
    }

    private static ICollection<T> GetCompatibleCollection<T>(ModelBindingContext bindingContext)
    {
        var model = bindingContext.Model;
        var modelType = bindingContext.ModelType;

        // There's a limited set of collection types we can create here.
        //
        // For the simple cases: Choose List<T> if the destination type supports it (at least as an intermediary).
        //
        // For more complex cases: If the destination type is a class that implements ICollection<T>, then activate
        // an instance and return that.
        //
        // Otherwise just give up.
        if (typeof(T).IsAssignableFrom(modelType))
        {
            return new List<T>();
        }

        if (modelType == typeof(T[]))
        {
            return new List<T>();
        }

        // Does collection exist and can it be reused?
        if (model is ICollection<T> collection && !collection.IsReadOnly)
        {
            collection.Clear();

            return collection;
        }

        if (modelType.IsAssignableFrom(typeof(List<T>)))
        {
            return new List<T>();
        }

        return (ICollection<T>)Activator.CreateInstance(modelType)!;
    }
}

Hi

liming.ma@volosoft.com

hi

Can you share a test project? I will download and check it ,then I will find out the reason. Thanks.

hi

Here is my test code, it works. What should I change to reproduce the exception?

Thanks

public class HomeController : AbpController
{
    public async Task<ActionResult> Index(MyFiles file)
    {
        using (var ms = new MemoryStream())
        {
            await file.Files.First().GetStream().CopyToAsync(ms);
            var filename = file.Files.First().FileName;
            var fileContent = ms.ToArray();
        }

        using (var ms = new MemoryStream())
        {
            await file.Files.Last().GetStream().CopyToAsync(ms);
            var filename = file.Files.Last().FileName;
            var fileContent = ms.ToArray();
        }

        return new OkResult();
    }
}

public class MyFiles
{
    public List<IRemoteStreamContent> Files { get; set; }
}

Showing 11 to 20 of 9254 entries
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 11, 2025, 10:10