Querying Data

We use all these methods in the CMS, so if you are not sure just clone the repo source and dig around, it should be fairly simple to understand.

Available Services

The following services are automatically injected in all components (defined in _Imports.razor):

  • IContentService - Content and ContentType queries

  • IMediaService - Media queries

  • IMembershipService - User and role queries

  • ILanguageService - Language and dictionary queries

  • ITagService - Tag queries

  • ISeoService - SEO and redirect queries

  • IDataService - Global data queries

  • IEmailService - Email operations

Getting Content Properties

In your IContentView components, the Content property is passed in automatically. You can access property values using these methods:

Simple Properties

Get a content property value by alias (property aliases are found on the Content Type page):

@(Content!.GetValue<string>("PropertyAlias"))
@(Content!.GetValue<int>("AmountPerPage"))
@(Content!.GetValue<bool>("ShowNavigation"))

The GetValue<TypeHere> accepts from types. Each content property has an example how how to use this method to get the data and the type to use. See the link below

Current Content Properties

To get media or content from a picker , it's a bit different, you need to pass in an instance of Mediatr. If you haven't defined it in the _imports like I have, make sure you Inject and instance of it.

await Content!.GetMedia("PropertyAlias", Mediator)
await Content!.GetContent("PropertyAlias", Mediator)

The GetValue method accepts any type. Each content property editor has documentation showing the type to use.

Media Picker Properties

To get media from a media picker property:

@code {
    private Media HeaderImage { get; set; } = new();
    
    protected override async Task OnInitializedAsync()
    {
        // Single media item
        HeaderImage = await Content!.GetMedia("HeaderImage", MediaService, "/fallback.jpg");
        
        // Multiple media items
        var images = await Content!.GetMediaItems("Gallery", MediaService);
        foreach (var image in images)
        {
            // Use image.Url, image.Name, etc.
        }
    }
}

Content Picker Properties

To get content from a content picker property:

@code {
    private Content? LinkedPage { get; set; }
    
    protected override async Task OnInitializedAsync()
    {
        // Single content item
        LinkedPage = await Content!.GetContent("RelatedPage", ContentService);
        
        // Multiple content items
        var relatedPages = await Content!.GetContentItems("RelatedPages", ContentService);
    }
}

Block List Editor Properties

To get content blocks from a Block List Editor:

@code {
    private IEnumerable<Content> ContentBlocks { get; set; } = [];
    
    protected override async Task OnInitializedAsync()
    {
        ContentBlocks = await Content!.GetBlocks("ContentBlocks", ContentService);
    }
}

Querying Content

Query Multiple Items

Use QueryContentAsync with QueryContentParameters to get multiple content items with filtering, sorting, and paging:

@code {
    private PaginatedList<Content> BlogPosts { get; set; } = new();
    
    protected override async Task OnInitializedAsync()
    {
        BlogPosts = await ContentService.QueryContentAsync(new QueryContentParameters
        {
            AmountPerPage = 10,
            PageIndex = 1,
            ContentTypeAlias = "BlogPost",
            OrderBy = GetContentsOrderBy.DateCreatedDescending,
            Cached = true
        });
    }
}

Query Parameters

QueryContentParameters supports these options:

public class QueryContentParameters
{
    public string ContentTypeAlias { get; set; } = string.Empty;
    public Guid? ContentTypeId { get; set; }
    public Guid? ParentId { get; set; }
    public bool AsNoTracking { get; set; } = true;
    public bool Cached { get; set; } = false;
    public List<Guid> Ids { get; set; } = [];
    public int PageIndex { get; set; } = 1;
    public int AmountPerPage { get; set; } = 10;
    public string? SearchTerm { get; set; }
    public bool IncludeChildren { get; set; }
    public bool IncludeUnpublished { get; set; }
    public bool RootContentOnly { get; set; }
    public GetContentsOrderBy OrderBy { get; set; } = GetContentsOrderBy.DateUpdatedDescending;
    public Expression<Func<Content, bool>>? WhereClause { get; set; }
    public Func<IQueryable<Content>>? Query { get; set; } // Advanced: Custom query override
}

Example with WhereClause

@code {
    protected override async Task OnInitializedAsync()
    {
        var posts = await ContentService.QueryContentAsync(new QueryContentParameters
        {
            AmountPerPage = 5,
            WhereClause = content => content.ParentId == Content!.Id && content.Published,
            OrderBy = GetContentsOrderBy.DateCreated
        });
    }
}

PaginatedList Result

All Query*Async methods return a PaginatedList<T> for server-side paging:

public class PaginatedList<T>
{
    public int PageIndex { get; set; }
    public int TotalPages { get; set; }
    public int TotalItems { get; set; }
    public IEnumerable<T> Items { get; set; }
    
    public bool HasPreviousPage => PageIndex > 1;
    public bool HasNextPage => PageIndex < TotalPages;
}

Usage example with pagination:

@foreach (var item in BlogPosts.Items)
{
    <BlogPostPreview Content="@item" />
}

@if (BlogPosts.TotalPages > 1)
{
    <Pagination 
        CurrentPage="@BlogPosts.PageIndex" 
        TotalPages="@BlogPosts.TotalPages" />
}

Get Single Item

Use Get*Async methods to retrieve a single item by ID:

@code {
    protected override async Task OnInitializedAsync()
    {
        // Get content by ID with children
        var page = await ContentService.GetContentAsync(new GetContentParameters
        {
            Id = contentId,
            IncludeChildren = true,
            IncludeParent = true,
            Cached = true
        });
        
        // Shorthand for simple get by ID
        var content = await ContentService.GetContent(contentId, cached: true);
    }
}

Querying Other Data Types

The same patterns apply to all other services:

Media

// Query multiple
var mediaItems = await MediaService.QueryMediaAsync(new QueryMediaParameters 
{ 
    AmountPerPage = 20,
    MediaTypes = [MediaType.Image],
    OrderBy = GetMediaOrderBy.DateCreatedDescending,
    Cached = true
});

// Get single
var media = await MediaService.GetMediaAsync(new GetMediaParameters 
{ 
    Id = mediaId,
    IncludeParent = true 
});

// Shorthand
var media = await MediaService.GetMedia(mediaId);

Users

// Query multiple
var users = await MembershipService.QueryUsersAsync(new QueryUsersParameters 
{ 
    AmountPerPage = 50,
    SearchTerm = "john",
    OrderBy = GetUsersOrderBy.Name
});

// Get single
var user = await MembershipService.GetUserAsync(new GetUserParameters 
{ 
    Id = userId 
});

Content Types

// Query multiple
var contentTypes = await ContentService.QueryContentTypesAsync(new QueryContentTypesParameters 
{ 
    IncludeElementTypes = false,
    RootOnly = true,
    OrderBy = GetContentTypesOrderBy.Name
});

// Get single
var contentType = await ContentService.GetContentTypeAsync(new GetContentTypeParameters 
{ 
    Id = contentTypeId 
});

Languages

// Query multiple
var languages = await LanguageService.QueryLanguagesAsync(new QueryLanguagesParameters 
{ 
    AmountPerPage = 100 
});

// Get single
var language = await LanguageService.GetLanguageAsync(new GetLanguageParameters 
{ 
    Id = languageId 
});

Domains

// Query multiple
var domains = await ContentService.QueryDomainAsync(new QueryDomainParameters 
{ 
    AmountPerPage = 50 
});

// Get single by URL
var domain = await ContentService.GetDomainAsync(new GetDomainParameters 
{ 
    Url = "example.com" 
});

Saving Data

Use Save*Async methods to create or update data. All save methods return a HandlerResult<T>:

@code {
    private async Task SaveContent()
    {
        var result = await ContentService.SaveContentAsync(new SaveContentParameters
        {
            Content = ContentToSave
        });
        
        if (result.Success)
        {
            // Success! result.Entity contains the saved entity
            var savedContent = result.Entity;
        }
        else
        {
            // Handle errors
            foreach (var message in result.Messages)
            {
                // message.Message, message.MessageType (Error, Warning, Info)
            }
        }
    }
}

HandlerResult

All save operations return a HandlerResult<T>:

public class HandlerResult<T>
{
    public T? Entity { get; set; }          // The saved entity
    public bool Success { get; set; }       // Whether operation succeeded
    public List<ResultMessage> Messages { get; set; } = [];  // Error/warning/info messages
    public bool RefreshSignIn { get; set; }  // Whether to refresh user session
}

Save Examples

// Save content
var contentResult = await ContentService.SaveContentAsync(new SaveContentParameters
{
    Content = myContent,
    UpdateContentRoles = true
});

// Save media
var mediaResult = await MediaService.SaveMediaAsync(new SaveMediaParameters
{
    MediaToSave = myMedia,
    FileToSave = uploadedFile,
    IsUpdate = false
});

// Save user
var userResult = await MembershipService.SaveUserAsync(new SaveUserParameters
{
    User = myUser,
    RoleIds = selectedRoleIds
});

Performance Tips

  1. Use caching: Set Cached = true for frequently accessed, rarely changing data

  2. AsNoTracking: Default is true for read operations (good for performance)

  3. Limit AmountPerPage: Don't request more items than you need

  4. Use Ids filter: When querying specific IDs, it automatically optimizes the query

  5. Leverage WhereClause: Filter at the database level for best performance

Last updated