A .NET library for creating, organizing and saving dynamic views with customizable filters, sorting, and pagination. Compatible with EF Core and Blazor.
- Customizable Views - Create and save views with specific columns, filters, sorting, and pagination settings
- Global & Private Views - Support for shared global views and user-specific private views
- Dynamic Filtering - Apply filters with various operators (equals, contains, greater than, etc.)
- Sorting - Sort data by any field in ascending or descending order
- Server-side Pagination - Efficient pagination for large datasets
- Favorites - Mark views as favorites for quick access
- EF Core Integration - Seamless integration with Entity Framework Core
- Blazor Support - Ready-to-use with Blazor WebAssembly and Server
dotnet add package DynamicViewsusing DynamicViews.Extensions;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add DynamicViews with database configuration
builder.Services.AddDynamicViews(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));using DynamicViews.Models;
using DynamicViews.Services;
public class ProductsController : Controller
{
private readonly IViewService _viewService;
private readonly AppDbContext _dbContext;
public ProductsController(IViewService viewService, AppDbContext dbContext)
{
_viewService = viewService;
_dbContext = dbContext;
}
public async Task<IActionResult> Index(Guid? viewId)
{
var userId = User.Identity?.Name ?? "anonymous";
ViewDto view;
if (viewId.HasValue)
{
view = await _viewService.GetViewAsync(viewId.Value, userId);
}
else
{
// Create a default view
view = new ViewDto
{
EntityType = "Product",
PageNumber = 1,
PageSize = 10,
Sort = new SortDefinition { Field = "Name", Direction = SortDirection.Ascending }
};
}
var result = await _viewService.ApplyViewAsync(_dbContext.Products.AsQueryable(), view);
return View(result);
}
}var newView = new ViewDto
{
Name = "Expensive Products",
EntityType = "Product",
IsGlobal = false,
Filters = new List<Filter>
{
new() { Field = "Price", Operator = FilterOperator.GreaterThan, Value = 100m }
},
Sort = new SortDefinition { Field = "Price", Direction = SortDirection.Descending },
PageSize = 20
};
var savedView = await _viewService.SaveViewAsync(newView, userId);// Get all available views for a user
Task<IEnumerable<ViewDto>> GetAvailableViewsAsync(string userId, string? entityType = null);
// Get a specific view
Task<ViewDto?> GetViewAsync(Guid viewId, string userId);
// Save a view (create or update)
Task<ViewDto> SaveViewAsync(ViewDto view, string userId);
// Delete a view
Task<bool> DeleteViewAsync(Guid viewId, string userId);
// Apply view configuration to a query
Task<PagedResult<T>> ApplyViewAsync<T>(IQueryable<T> query, ViewDto view);
// Set/unset favorite
Task SetFavoriteAsync(Guid viewId, string userId, bool isFavorite);
// Get favorite views
Task<IEnumerable<ViewDto>> GetFavoriteViewsAsync(string userId, string? entityType = null);
// Duplicate a view
Task<ViewDto?> DuplicateViewAsync(Guid viewId, string newName, string userId);// Apply filters to a query
IQueryable<T> ApplyFilters<T>(this IQueryable<T> query, IEnumerable<Filter>? filters);
// Apply sorting to a query
IQueryable<T> ApplySorting<T>(this IQueryable<T> query, SortDefinition? sort);
// Apply pagination to a query
IQueryable<T> ApplyPagination<T>(this IQueryable<T> query, int pageNumber, int pageSize);Equals/NotEqualsGreaterThan/GreaterThanOrEqualsLessThan/LessThanOrEqualsContains/StartsWith/EndsWithIsNull/IsNotNull
public class ViewDto
{
public Guid Id { get; set; }
public string Name { get; set; }
public string? Description { get; set; }
public string EntityType { get; set; }
public bool IsGlobal { get; set; }
public bool IsFavorite { get; set; }
public List<ColumnDefinition> Columns { get; set; }
public List<Filter> Filters { get; set; }
public SortDefinition? Sort { get; set; }
public int PageNumber { get; set; }
public int PageSize { get; set; }
}public class Filter
{
public string Field { get; set; }
public FilterOperator Operator { get; set; }
public object? Value { get; set; }
}public class PagedResult<T>
{
public IEnumerable<T> Items { get; set; }
public int PageNumber { get; set; }
public int PageSize { get; set; }
public int TotalCount { get; set; }
public int TotalPages { get; }
public bool HasPreviousPage { get; }
public bool HasNextPage { get; }
}The repository includes a Blazor Web App sample that demonstrates all features:
cd samples/DynamicViews.Sample
dotnet runThen navigate to https://localhost:5001/products to see the demo.
The library uses Entity Framework Core and requires these tables:
Views- Stores view configurationsUserViews- Associates users with their views and favoritesSavedFilters- Stores reusable filter configurations
For EF Core migrations:
// In your migration, ensure DynamicViewsDbContext is included
services.AddDynamicViews(options =>
options.UseSqlServer(connectionString));- Views validate field names against entity properties to prevent injection
- Global views can only be modified by administrators
- User views are isolated by user ID
MIT