Hayou.DynamicFieldManagement.HttpApi 0.1.0

The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package Hayou.DynamicFieldManagement.HttpApi --version 0.1.0
                    
NuGet\Install-Package Hayou.DynamicFieldManagement.HttpApi -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Hayou.DynamicFieldManagement.HttpApi" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Hayou.DynamicFieldManagement.HttpApi" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Hayou.DynamicFieldManagement.HttpApi" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Hayou.DynamicFieldManagement.HttpApi --version 0.1.0
                    
#r "nuget: Hayou.DynamicFieldManagement.HttpApi, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Hayou.DynamicFieldManagement.HttpApi@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Hayou.DynamicFieldManagement.HttpApi&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Hayou.DynamicFieldManagement.HttpApi&version=0.1.0
                    
Install as a Cake Tool

动态属性模块


动态属性模块可实现对现有实体添加动态字段的功能,并能在将照一定的约定配置后,可方便的管理动态字段。

用法:

1、添加相应的模块引用,并在webHost项目模块中添加模块依赖

为 webHost 模块添加以下模块的引用,

Hayou.DynaimcFieldManagement.Application
Hayou.DynaimcFieldManagement.Domain
Hayou.DynaimcFieldManagement.EntityFrameworkCore
Hayou.DynaimcFieldManagement.Web

添加模块依赖

[DependsOn(
    typeof(DynamicFieldManagementWebModule),
    typeof(DynamicFieldManagementApplicationModule),
    typeof(DynamicFieldManagementHttpApiModule),
    typeof(DynamicFieldManagementEntityFrameworkCoreModule),
    ...
        )]
public class xxxWebUnifiedModule : AbpModule{
}

2、在DemoDbContext的 OnModelCreating 方法中添加实体配置 builder.ConfigureDynamicFieldManagement();

public class DemoDbContext : AbpDbContext<DemoDbContext>
{
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        /* Configure your own entities here */
        
        builder.ConfigureDynamicFieldManagement();
    }
}

在程序包管理控制台里添加 迁移文件,并执行迁移

add-migration Add-DynamicFieldEntities
update-database

这样在项目中就可以定义和管理动态字段了。

3、需要添加动态属性的实体和 dto 需要继承自 IHasDynamicFields 。

//实体定义
[Display(Name = "图书")]
public class Book : AuditedEntity<Guid>, IMultiTenant, IHasDynamicFields
{

    public ExtraPropertyDictionary ExtraProperties { get; set; } =  new();
}

//Dto定义
public class BookDto : AuditedEntityDto<Guid>, IMultiTenant, IHasDynamicFields
{

    public ExtraPropertyDictionary ExtraProperties { get; set; } =  new();
}

只有继承了IHasDynamicFields 和基类继承自 Entity<Guid> 的实体,才可以配置动态字段。为实体类添加 Display特性,可使用显示特性来为实体提供更友好的名称。

4、在服务层对GetListAsync、GetAsync 方法添加对动态字段的填充

    public override async Task<PagedResultDto<BookDto>> GetListAsync(PagedAndSortedResultRequestDto input)
    {
        await CheckGetListPolicyAsync();
        var query = await CreateFilteredQueryAsync(input);
        var totalCount = await AsyncExecuter.CountAsync(query);
        query = ApplySorting(query, input);
        query = ApplyPaging(query, input);
        var entities = await AsyncExecuter.ToListAsync(query);

        //填充动态字段
        var dynamicFieldManagement = LazyServiceProvider.GetRequiredService<IDynamicFieldManager<Book>>();
        entities = await dynamicFieldManagement?.FillEntityDynamicValuesAsync(entities, true);

        var dtos = await MapToGetListOutputDtosAsync(entities);
        return new PagedResultDto<BookDto>(
            totalCount,
            dtos
        );
    }

    public override async Task<BookDto> GetAsync(Guid id)
    {
        var entity = await Repository.GetAsync(id);
        
        //填充动态字段
        var dynamicFieldManagement = LazyServiceProvider.GetRequiredService<IDynamicFieldManager<Book>>();
        entity = await dynamicFieldManagement?.FillEntityDynamicValuesAsync(entity, true);

        return await MapToGetOutputDtoAsync(entity);
    }


5、在Asp.net Razor 页面的UI层的处理:

定义页面模型基类 PageModelWithDynamicField<TEntity> ,在基类中提供为创建和编辑页以及详情页提供动态字段的加载与保存的方法, 然后页面继承自这个类就可以了。


public abstract class PageModelWithDynamicField<TEntity> : AbpPageModel where TEntity : Entity<Guid>
{
    private IDynamicFieldManager<TEntity>? _dynamicFieldManager;

    protected ManagementWithDynamicFieldPageModel()
    {

    }

    public IDynamicFieldManager<TEntity> DynamicFieldManager
    {
        get
        {
            if (_dynamicFieldManager == null)
                _dynamicFieldManager = LazyServiceProvider.LazyGetRequiredService<IDynamicFieldManager<TEntity>>();
            return _dynamicFieldManager;
        }
    }

    [BindProperty]
    public Dictionary<string, string> DynamicFields { get; set; } = new();

    /// <summary>
    /// 保存动态字段值
    /// </summary>
    /// <param name="entityId"></param>
    /// <param name="associationId"></param>
    /// <param name="tenantId"></param>
    /// <returns></returns>
    public async Task SaveDynamicFieldValues(Guid entityId, Guid? associationId, Guid? tenantId)
    {
        if (DynamicFields?.Keys.Count > 0)
            await DynamicFieldManager.SetEntityDynamicValuesAsync(entityId, DynamicFields, associationId, tenantId);
    }

    /// <summary>
    /// 渲染动态字段表单
    /// </summary>
    /// <returns></returns>
    public async Task<string> RenderDynamicFieldsAsHtmlFormAsync(Guid? entityId = null, Guid? associationId = null, Guid? tenantId = null)
    {
        return (await DynamicFieldManager.GetDynamicFieldRenderHtmlFormAsync(entityId, associationId, tenantId ?? CurrentTenant.Id));
    }

    /// <summary>
    /// 渲染动态字段为表格行数据
    /// </summary>
    /// <param name="entityId"></param>
    /// <param name="keyIsDisplayName"></param>
    /// <returns></returns>
    public async Task<string> RenderDynamicFieldsAsHtmlTableRowsAsync(Guid entityId, bool keyIsDisplayName = false)
    {
        var result = string.Empty;
        var dynamicFields = await DynamicFieldManager.GetEntityDynamicValuesAsync(entityId, keyIsDisplayName);
        if (dynamicFields?.Keys.Count > 0)
        {
            result = string.Join("\n", dynamicFields!.Select(p => $"<tr>\r\n<td>{p.Key}</td>\r\n<th>{p.Value} </th>\r\n</tr>"));
        }
        return result;
    }

    public async Task<string> RenderDynamicFieldsAsHtmlTableRowsAsync(Dictionary<string, string> dynamicFields)
    {
        var result = string.Empty;

        if (dynamicFields?.Keys.Count > 0)
        {
            result = string.Join("\n", dynamicFields!.Select(p => $"<tr>\r\n<td>{p.Key}</td>\r\n<th>{p.Value} </th>\r\n</tr>"));
        }

        return await Task.FromResult(result);
    }


    public async Task<string> RenderDynamicFieldsAsHtmlTableRowsAsync(ExtraPropertyDictionary extraPropertyDictionary)
    {
        var result = string.Empty;

        if (extraPropertyDictionary?.ContainsKey("dynamicFields") == true)
        {
            var dynamicFields = extraPropertyDictionary["dynamicFields"] as Dictionary<string, string>;

            if (dynamicFields?.Keys.Count > 0)
            {
                result = string.Join("\n", dynamicFields!.Select(p => $"<tr>\r\n<td>{p.Key}</td>\r\n<th>{p.Value} </th>\r\n</tr>"));
            }
        }
        return await Task.FromResult(result);
    }
}




6、在Index.cshtml页面代码中添加动态属性脚本的引用:

@section scripts {
    <abp-script-bundle name="@(typeof(IndexModel).FullName)">
        <abp-script src="/Pages/Book/Index.cshtml.js" />
    </abp-script-bundle>

    <script src="/Abp/DynamicFieldScript"></script>
}

这样可以提前缓存动态字段的定义到浏览器缓存,以便在列表里能显示这些动态字段列。

7、在Index.cshtml.js 脚本代码中添加动态属性列的定义:

var columnDefs = [ ... ];
columnDefs = abp.dynamicFields.dynamicFieldColumnDef("book", columnDefs, ['F1', 'F2', 'F3', 'F4', 'F5']);

这样在列表 datatable 渲染后就会出现动态属性。 如果不需要在列表中显示动态字段,可不进行 6和7的操作。

8、在CreateModal.cshtml.cs 和 EditModal.cshtml.cs 中的基类修改为 PageModelWithDynamicField<FloorPlan>, 并在 OnPostAsync() 方法中提交修改后 调用 await base.SaveDynamicFieldValues(dto.Id, null, dto.TenantId); 保存动态字段的值;

public class CreateModalModel : PageModelWithDynamicField<Book>
    {
        ...

        public async Task<IActionResult> OnPostAsync()
        {
            if (ModelState.IsValid)
            {
                var dto = await _bookPlanAppService.CreateAsync(Book);// or _bookPlanAppService.UpdateAsync(Book) in EditModalModel

                await base.SaveDynamicFieldValues(dto.Id, null, dto.TenantId);

                return Content("");
            }
            throw new UserFriendlyException("Error");
        }

    }

9、在CreateModal.cshtml 和 EditModal.cshtml 中添加 以下代码 显示动态字段的表单:

//新建界面中:
@Html.Raw(await Model.RenderDynamicFieldsAsHtmlFormAsync())

//编辑界面中:
 @Html.Raw(await Model.RenderDynamicFieldsAsHtmlFormAsync(Model.Id, null, Model.Book.TenantId))

10、在 DetailModal.cshtml.cs 中的基类修改为 PageModelWithDynamicField<FloorPlan>:

public class DetailModalModel : PageModelWithDynamicField<Book>
{

}

11、在 DetailModal.cshtml 中添加 以下代码 显示动态字段的表单:

 @Html.Raw(await Model.RenderDynamicFieldsAsHtmlTableRowsAsync(Model.Book.ExtraProperties))

12、使用Redis缓存

在appsettings.json中可添加缓存配置以使用缓存提升性能

  "Redis": {
    "IsEnabled": true,
    "Configuration": "127.0.0.1:6379,password=[password],defaultdatabase=1,abortConnect=false"
  },
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated