Activities of "liangshiwei"

1

update to Angular

2

update HttpApiHostProjectDirectory

okay

you can check the new project settings.

Please contact to license@abp.io to purchase a license

you can send an email to license@abp.io

I'm closing this and refunded your ticket.

The ng directory is incorrect .

you can create a new ng project with suite to check what's the path config

%UserProfile%\.abp\suite

Hi,

The CLI gets apiname by command option, you can specify it.

https://abp.io/docs/latest/cli#options-15

yes, you can open your .abp/suite folder to update the appsettings.json

3 is Angular UI

it's generating empty components, and the URL isn't visible in the menu. How do I map the permissions for this? Or is there a different way to generate a complete UI using the ABP CLI?

you can use abp suite to generate code.

Hi, It's hard to find the problem in a few minutes.

I guess the problem is related to your DTO property types.

you can override the IApiDescriptionModelProvider service and check the logs.

public static class ArrayMatcher
{
    public static T[] Match<T>(T[] sourceArray, T[] destinationArray)
    {
        var result = new List<T>();

        var currentMethodParamIndex = 0;
        var parentItem = default(T);

        foreach (var sourceItem in sourceArray)
        {
            if (currentMethodParamIndex < destinationArray.Length)
            {
                var destinationItem = destinationArray[currentMethodParamIndex];

                if (EqualityComparer<T>.Default.Equals(sourceItem, destinationItem))
                {
                    parentItem = default;
                    currentMethodParamIndex++;
                }
                else
                {
                    if (parentItem == null)
                    {
                        parentItem = destinationItem;
                        currentMethodParamIndex++;
                    }
                }
            }

            var resultItem = EqualityComparer<T>.Default.Equals(parentItem, default) ? sourceItem : parentItem;
            result.Add(resultItem!);
        }

        return result.ToArray();
    }
}

[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IApiDescriptionModelProvider))]
public class MyAspNetCoreApiDescriptionModelProvider : IApiDescriptionModelProvider, ITransientDependency
{
    public ILogger<MyAspNetCoreApiDescriptionModelProvider> Logger { get; set; }

    private readonly AspNetCoreApiDescriptionModelProviderOptions _options;
    private readonly IApiDescriptionGroupCollectionProvider _descriptionProvider;
    private readonly AbpAspNetCoreMvcOptions _abpAspNetCoreMvcOptions;
    private readonly AbpApiDescriptionModelOptions _modelOptions;

    public MyAspNetCoreApiDescriptionModelProvider(
        IOptions<AspNetCoreApiDescriptionModelProviderOptions> options,
        IApiDescriptionGroupCollectionProvider descriptionProvider,
        IOptions<AbpAspNetCoreMvcOptions> abpAspNetCoreMvcOptions,
        IOptions<AbpApiDescriptionModelOptions> modelOptions)
    {
        _options = options.Value;
        _descriptionProvider = descriptionProvider;
        _abpAspNetCoreMvcOptions = abpAspNetCoreMvcOptions.Value;
        _modelOptions = modelOptions.Value;

        Logger = NullLogger<MyAspNetCoreApiDescriptionModelProvider>.Instance;
    }

    public ApplicationApiDescriptionModel CreateApiModel(ApplicationApiDescriptionModelRequestDto input)
    {
        //TODO: Can cache the model?

        var model = ApplicationApiDescriptionModel.Create();

        foreach (var descriptionGroupItem in _descriptionProvider.ApiDescriptionGroups.Items)
        {
            foreach (var apiDescription in descriptionGroupItem.Items)
            {
                if (!apiDescription.ActionDescriptor.IsControllerAction())
                {
                    continue;
                }

                AddApiDescriptionToModel(apiDescription, model, input);
            }
        }

        foreach (var (_, module) in model.Modules)
        {
            var controllers = module.Controllers.GroupBy(x => x.Value.Type).ToList();
            foreach (var controller in controllers.Where(x => x.Count() > 1))
            {
                var removedController = module.Controllers.RemoveAll(x => x.Value.IsRemoteService && controller.OrderBy(c => c.Value.ControllerGroupName).Skip(1).Contains(x));
                foreach (var removed in removedController)
                {
                    Logger.LogInformation($"The controller named '{removed.Value.Type}' was removed from ApplicationApiDescriptionModel because it same with other controller.");
                }
            }
        }

        model.NormalizeOrder();
        return model;
    }

    private void AddApiDescriptionToModel(
        ApiDescription apiDescription,
        ApplicationApiDescriptionModel applicationModel,
        ApplicationApiDescriptionModelRequestDto input)
    {
        var controllerType = apiDescription
            .ActionDescriptor
            .AsControllerActionDescriptor()
            .ControllerTypeInfo;

        var setting = FindSetting(controllerType);

        var moduleModel = applicationModel.GetOrAddModule(
            GetRootPath(controllerType, apiDescription.ActionDescriptor, setting),
            GetRemoteServiceName(controllerType, setting)
        );

        var controllerModel = moduleModel.GetOrAddController(
            _options.ControllerNameGenerator(controllerType, setting),
            FindGroupName(controllerType) ?? apiDescription.GroupName,
            apiDescription.IsRemoteService(),
            apiDescription.IsIntegrationService(),
            apiDescription.GetProperty<ApiVersion>()?.ToString(),
            controllerType,
            _modelOptions.IgnoredInterfaces
        );

        var method = apiDescription.ActionDescriptor.GetMethodInfo();

        var uniqueMethodName = _options.ActionNameGenerator(method);
        if (controllerModel.Actions.ContainsKey(uniqueMethodName))
        {
            Logger.LogWarning(
                $"Controller '{controllerModel.ControllerName}' contains more than one action with name '{uniqueMethodName}' for module '{moduleModel.RootPath}'. Ignored: " +
                method);
            return;
        }

        Logger.LogDebug($"ActionApiDescriptionModel.Create: {controllerModel.ControllerName}.{uniqueMethodName}");

        bool? allowAnonymous = null;
        if (apiDescription.ActionDescriptor.EndpointMetadata.Any(x => x is IAllowAnonymous))
        {
            allowAnonymous = true;
        }
        else if (apiDescription.ActionDescriptor.EndpointMetadata.Any(x => x is IAuthorizeData))
        {
            allowAnonymous = false;
        }

        var implementFrom = controllerType.FullName;

        var interfaceType = controllerType.GetInterfaces().FirstOrDefault(i => i.GetMethods().Any(x => x.ToString() == method.ToString()));
        if (interfaceType != null)
        {
            implementFrom = TypeHelper.GetFullNameHandlingNullableAndGenerics(interfaceType);
        }

        var actionModel = controllerModel.AddAction(
            uniqueMethodName,
            ActionApiDescriptionModel.Create(
                uniqueMethodName,
                method,
                apiDescription.RelativePath!,
                apiDescription.HttpMethod,
                GetSupportedVersions(controllerType, method, setting),
                allowAnonymous,
                implementFrom
            )
        );

        if (input.IncludeTypes)
        {
            AddCustomTypesToModel(applicationModel, method);
        }

        AddParameterDescriptionsToModel(actionModel, method, apiDescription);
    }

    private static List<string> GetSupportedVersions(Type controllerType, MethodInfo method,
        ConventionalControllerSetting? setting)
    {
        var supportedVersions = new List<ApiVersion>();

        var mapToAttributes = method.GetCustomAttributes<MapToApiVersionAttribute>().ToArray();
        if (mapToAttributes.Any())
        {
            supportedVersions.AddRange(
                mapToAttributes.SelectMany(a => a.Versions)
            );
        }
        else
        {
            supportedVersions.AddRange(
                controllerType.GetCustomAttributes<ApiVersionAttribute>().SelectMany(a => a.Versions)
            );

            setting?.ApiVersions.ForEach(supportedVersions.Add);
        }

        return supportedVersions.Select(v => v.ToString()).Distinct().ToList();
    }

    private void AddCustomTypesToModel(ApplicationApiDescriptionModel applicationModel, MethodInfo method)
    {
        foreach (var parameterInfo in method.GetParameters())
        {
            try
            {
                AddCustomTypesToModel(applicationModel, parameterInfo.ParameterType);
            }
            catch(Exception e)
            {
                Logger.LogError($"Error while adding parameter type to model, method info: {method.Name}, parameter info: {parameterInfo.Name}, parameter type: {parameterInfo.ParameterType.FullName}");
                throw e;
            }
            
        }

        try
        {
            AddCustomTypesToModel(applicationModel, method.ReturnType);
        }
        catch (Exception e)
        {
            Logger.LogError($"Error while adding return type to model, method info: {method.Name}, return type: {method.ReturnType.FullName}");
            throw e;
        }

        
    }

    private static void AddCustomTypesToModel(ApplicationApiDescriptionModel applicationModel,
        Type? type)
    {
        if (type == null)
        {
            return;
        }

        if (type.IsGenericParameter)
        {
            return;
        }

        type = AsyncHelper.UnwrapTask(type);

        if (type == typeof(object) ||
            type == typeof(void) ||
            type == typeof(Enum) ||
            type == typeof(ValueType) ||
            type == typeof(DateOnly) ||
            type == typeof(TimeOnly) ||
            TypeHelper.IsPrimitiveExtended(type))
        {
            return;
        }

        if (TypeHelper.IsDictionary(type, out var keyType, out var valueType))
        {
            AddCustomTypesToModel(applicationModel, keyType);
            AddCustomTypesToModel(applicationModel, valueType);
            return;
        }

        if (TypeHelper.IsEnumerable(type, out var itemType))
        {
            AddCustomTypesToModel(applicationModel, itemType);
            return;
        }

        if (type.IsGenericType && !type.IsGenericTypeDefinition)
        {
            var genericTypeDefinition = type.GetGenericTypeDefinition();

            AddCustomTypesToModel(applicationModel, genericTypeDefinition);

            foreach (var genericArgument in type.GetGenericArguments())
            {
                AddCustomTypesToModel(applicationModel, genericArgument);
            }

            return;
        }

        var typeName = CalculateTypeName(type);
        if (applicationModel.Types.ContainsKey(typeName))
        {
            return;
        }

        applicationModel.Types[typeName] = TypeApiDescriptionModel.Create(type);

        AddCustomTypesToModel(applicationModel, type.BaseType);

        foreach (var propertyInfo in type.GetProperties().Where(p => p.DeclaringType == type))
        {
            AddCustomTypesToModel(applicationModel, propertyInfo.PropertyType);
        }
    }

    private static string CalculateTypeName(Type type)
    {
        if (!type.IsGenericTypeDefinition)
        {
            return TypeHelper.GetFullNameHandlingNullableAndGenerics(type);
        }

        var i = 0;
        var argumentList = type
            .GetGenericArguments()
            .Select(_ => "T" + i++)
            .JoinAsString(",");

        return $"{type.FullName!.Left(type.FullName!.IndexOf('`'))}&lt;{argumentList}&gt;";
    }

    private void AddParameterDescriptionsToModel(ActionApiDescriptionModel actionModel, MethodInfo method,
        ApiDescription apiDescription)
    {
        if (!apiDescription.ParameterDescriptions.Any())
        {
            return;
        }

        var parameterDescriptionNames = apiDescription
            .ParameterDescriptions
            .Select(p => p.Name)
            .ToArray();

        var methodParameterNames = method
            .GetParameters()
            .Where(IsNotFromServicesParameter)
            .Select(GetMethodParamName)
            .ToArray();

        var matchedMethodParamNames = ArrayMatcher.Match(
            parameterDescriptionNames,
            methodParameterNames
        );

        for (var i = 0; i &lt; apiDescription.ParameterDescriptions.Count; i++)
        {
            var parameterDescription = apiDescription.ParameterDescriptions[i];
            var matchedMethodParamName = matchedMethodParamNames.Length &gt; i
                ? matchedMethodParamNames[i]
                : parameterDescription.Name;

            actionModel.AddParameter(ParameterApiDescriptionModel.Create(
                    parameterDescription.Name,
                    _options.ApiParameterNameGenerator?.Invoke(parameterDescription),
                    matchedMethodParamName,
                    parameterDescription.Type,
                    parameterDescription.RouteInfo?.IsOptional ?? false,
                    parameterDescription.RouteInfo?.DefaultValue,
                    parameterDescription.RouteInfo?.Constraints?.Select(c => c.GetType().Name).ToArray(),
                    parameterDescription.Source.Id,
                    parameterDescription.ModelMetadata?.ContainerType != null
                        ? parameterDescription.ParameterDescriptor?.Name ?? string.Empty
                        : string.Empty
                )
            );
        }
    }

    private static bool IsNotFromServicesParameter(ParameterInfo parameterInfo)
    {
        return !parameterInfo.IsDefined(typeof(FromServicesAttribute), true);
    }

    public string GetMethodParamName(ParameterInfo parameterInfo)
    {
        var modelNameProvider = parameterInfo.GetCustomAttributes()
            .OfType&lt;IModelNameProvider&gt;()
            .FirstOrDefault();

        if (modelNameProvider == null)
        {
            return parameterInfo.Name!;
        }

        return (modelNameProvider.Name ?? parameterInfo.Name)!;
    }

    private static string GetRootPath(
        [NotNull] Type controllerType,
        [NotNull] ActionDescriptor actionDescriptor,
        ConventionalControllerSetting? setting)
    {
        if (setting != null)
        {
            return setting.RootPath;
        }

        var areaAttr = controllerType.GetCustomAttributes().OfType&lt;AreaAttribute&gt;().FirstOrDefault() ?? actionDescriptor.EndpointMetadata.OfType&lt;AreaAttribute&gt;().FirstOrDefault();
        if (areaAttr != null)
        {
            return areaAttr.RouteValue;
        }

        return ModuleApiDescriptionModel.DefaultRootPath;
    }

    private string GetRemoteServiceName(Type controllerType, ConventionalControllerSetting? setting)
    {
        if (setting != null)
        {
            return setting.RemoteServiceName;
        }

        var remoteServiceAttr =
            controllerType.GetCustomAttributes().OfType&lt;RemoteServiceAttribute&gt;().FirstOrDefault();
        if (remoteServiceAttr?.Name != null)
        {
            return remoteServiceAttr.Name;
        }

        return ModuleApiDescriptionModel.DefaultRemoteServiceName;
    }

    private string? FindGroupName(Type controllerType)
    {
        var controllerNameAttribute =
            controllerType.GetCustomAttributes().OfType&lt;ControllerNameAttribute&gt;().FirstOrDefault();

        if (controllerNameAttribute?.Name != null)
        {
            return controllerNameAttribute.Name;
        }

        return null;
    }

    private ConventionalControllerSetting? FindSetting(Type controllerType)
    {
        foreach (var controllerSetting in _abpAspNetCoreMvcOptions.ConventionalControllers.ConventionalControllerSettings)
        {
            if (controllerSetting.GetControllerTypes().Contains(controllerType))
            {
                return controllerSetting;
            }
        }

        return null;
    }
}
Showing 611 to 620 of 5968 entries
Made with ❤️ on ABP v9.1.0-preview. Updated on November 11, 2024, 11:11