Hayou.Abp.AspNetCore.Mvc.UI.RazorPages.DynamicField 0.2.0

dotnet add package Hayou.Abp.AspNetCore.Mvc.UI.RazorPages.DynamicField --version 0.2.0
                    
NuGet\Install-Package Hayou.Abp.AspNetCore.Mvc.UI.RazorPages.DynamicField -Version 0.2.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.Abp.AspNetCore.Mvc.UI.RazorPages.DynamicField" Version="0.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Hayou.Abp.AspNetCore.Mvc.UI.RazorPages.DynamicField" Version="0.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Hayou.Abp.AspNetCore.Mvc.UI.RazorPages.DynamicField" />
                    
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.Abp.AspNetCore.Mvc.UI.RazorPages.DynamicField --version 0.2.0
                    
#r "nuget: Hayou.Abp.AspNetCore.Mvc.UI.RazorPages.DynamicField, 0.2.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.Abp.AspNetCore.Mvc.UI.RazorPages.DynamicField@0.2.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.Abp.AspNetCore.Mvc.UI.RazorPages.DynamicField&version=0.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Hayou.Abp.AspNetCore.Mvc.UI.RazorPages.DynamicField&version=0.2.0
                    
Install as a Cake Tool

动态属性模块


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

用法:

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

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

Hayou.Abp.DynaimcFieldManagement.Application
Hayou.Abp.DynaimcFieldManagement.Domain
Hayou.Abp.DynaimcFieldManagement.EntityFrameworkCore
Hayou.Abp.DynaimcFieldManagement.Web
Hayou.Abp.AspNetCore.Mvc.UI.RazorPages.DynamicField  //在需要引入动态字段的UI界面所在的Web项目中引用

添加模块依赖

[DependsOn(
    // ABP DynamicField packages
    typeof(HayouAbpDynamicFieldManagementApplicationModule),
    typeof(HayouAbpDynamicFieldManagementHttpApiModule),
    typeof(HayouAbpDynamicFieldManagementEntityFrameworkCoreModule),
    typeof(HayouAbpDynamicFieldManagementWebModule),
    ...
        )]
public class xxxWebUnifiedModule : AbpModule{
}

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

public class DemoDbContext : AbpDbContext<DemoDbContext>
{
    protected override void OnModelCreating(ModelBuilder 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、在服务层对GetListAsyncGetAsync 方法添加对动态字段的填充(可选)

    public override async Task<PagedResultDto<BookDto>> GetListAsync(PagedAndSortedResultRequestDto input)
    {
        var query = await CreateFilteredQueryAsync(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);

        return await MapToGetOutputDtoAsync(entity);
    }

在Asp.net Razor 页面UI层的使用:

5、在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>
}

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

6、在Index.cshtml.js 脚本代码中添加动态属性列的定义(可选):


var columnDefs = [ ... ];

columnDefs = abp.dynamicFields.dynamicFieldColumnDef("book", columnDefs, ['F01', 'F02']);// 只显示 F01和F02两个动态字段
//columnDefs = abp.dynamicFields.dynamicFieldColumnDef("book", columnDefs,null,null);// 显示全部字段

dynamicFieldColumnDef方法有四个参数,分别是:实体名,列定义数组,显示字段数组,渲染函数。 默认渲染函数:


function render(data, type, row, meta, name){
   return row && row.extraProperties && row.extraProperties.dynamicFields && row.extraProperties.dynamicFields[name] ? row.extraProperties.dynamicFields[name] : '';
}

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

7、页面基类 DemoBasePageModel.cs 中添加一个同名的泛型类 DemoBasePageModel<TEntity> 继承自 PageModelWithDynamicField<TEntity> 。需要引用 Hayou.Abp.AspNetCore.Mvc.UI.RazorPages.DynamicField


public abstract class DemoBasePageModel: AbpPageModel
{
    protected DynamicFieldDemoPageModel()
    {
        LocalizationResourceType = typeof(DynamicFieldDemoResource);
    }
}

// 添加这个同名的泛型基类
public abstract class DemoBasePageModel<TEntity> : PageModelWithDynamicField<TEntity> where TEntity : Entity<Guid>
{
    protected DemoBasePageModel()
    {
        LocalizationResourceType = typeof(DemoResource);
    }

    //在这里可以重新定义在详情页显示动态字段的方式,默认是渲染成 html table 的 tr/td。
    public override string RenderValue(DynamicFieldValueMiniDto value)
    {
        return base.RenderValue(value);
    }
}

基类中 RenderValue 的默认实现如下,可在重写时自行修改

public string RenderValue(DynamicFieldValueMiniDto value)
{
    var valueString = string.Empty;
    if (!value.StringValue.IsNullOrWhiteSpace())
    {
        valueString = value.FieldType switch
        {
            EnFieldType.Url => $"<a href=\"{value.StringValue}\" target=\"_blank\">{value.StringValue}</a>",
            EnFieldType.ImgUrl => $"<img src=\"{value.StringValue}\" class=\"img-thumbnail\" target=\"_blank\" />",
            _ => value.StringValue
        };
    }
    return $"\t\t<tr>\r\n\t\t\t<td>{value.DisplayName ?? value.FieldName}</td>\r\n\t\t\t<th>{valueString} </th>\r\n\t\t</tr>";
}

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


public class CreateModalModel : DemoBasePageModel<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.cshtmlEditModal.cshtml 中添加 以下代码 显示动态字段的表单:


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

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

10、在 DetailModal.cshtml.cs 中的基类修改为 DemoBasePageModel<Book>


public class DetailModalModel : DemoBasePageModel<Book>
{

}

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


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

如果在第4步的服务层没有填充动态字段值,那就需要直接从服务器获取数据,可使用下面的这个方法:

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

12、使用Redis缓存

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

  "Redis": {
    "IsEnabled": true,
    "Configuration": "127.0.0.1:6379,password=[password],defaultdatabase=1,abortConnect=false"
  },

版本更新说明:

v0.2.0:

1、升级对.net10.0 和 abp vnext 10.0的支持,移除去 AutoMapper的支持

v0.1.6:

1、优化动态字段表单内容的本地验证和服务端验证

v0.1.5:

1、修复编辑时取不到动态字段值的问题
2、修改了无法取到多选列表框选中的多个值的问题。

v0.1.4:

1、增加链接地址、图片地址、邮箱地址类型的数据支持
2、增加对缓存的处理
3、页面模型基类简化,并能通过重写RenderValue方法修改详情页的动态字段的显示方式。

v0.1.3:

1、添加对动态值的修改功能,修改时按数据类型提供修改控件
2、增加对多选框和长文本的支持
3、修复布尔类型动态字段在编辑时无法选中的问题。
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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
0.2.0 195 11/24/2025
0.1.6 184 9/24/2025
0.1.5 176 9/24/2025
0.1.4 183 9/23/2025