Skip to content

agriffard/DynamicViews

Repository files navigation

DynamicViews

A .NET library for creating, organizing and saving dynamic views with customizable filters, sorting, and pagination. Compatible with EF Core and Blazor.

Features

  • 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

Installation

dotnet add package DynamicViews

Quick Start

1. Configure Services

using 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")));

2. Inject and Use the View Service

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);
    }
}

3. Save a Custom View

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);

API Reference

IViewService

// 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);

Extension Methods

// 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);

Filter Operators

  • Equals / NotEquals
  • GreaterThan / GreaterThanOrEquals
  • LessThan / LessThanOrEquals
  • Contains / StartsWith / EndsWith
  • IsNull / IsNotNull

Models

ViewDto

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; }
}

Filter

public class Filter
{
    public string Field { get; set; }
    public FilterOperator Operator { get; set; }
    public object? Value { get; set; }
}

PagedResult

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; }
}

Sample Application

The repository includes a Blazor Web App sample that demonstrates all features:

cd samples/DynamicViews.Sample
dotnet run

Then navigate to https://localhost:5001/products to see the demo.

Database Setup

The library uses Entity Framework Core and requires these tables:

  • Views - Stores view configurations
  • UserViews - Associates users with their views and favorites
  • SavedFilters - Stores reusable filter configurations

For EF Core migrations:

// In your migration, ensure DynamicViewsDbContext is included
services.AddDynamicViews(options =>
    options.UseSqlServer(connectionString));

Security

  • 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

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages