> For the complete documentation index, see [llms.txt](https://aptitude.gitbook.io/zaubercms/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://aptitude.gitbook.io/zaubercms/creating-a-website/querying-data.md).

# Querying Data

### 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):

```csharp
@(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

{% content-ref url="/pages/KXKmtDvzsXIGBaMixGfC" %}
[Current Content Properties](/zaubercms/creating-a-website/current-content-properties.md)
{% endcontent-ref %}

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.

```csharp
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:

```csharp
@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:

```csharp
@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:

```csharp
@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:

```csharp
@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:

```csharp
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

```csharp
@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:

```csharp
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:

```csharp
@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:

```csharp
@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

```csharp
// 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

```csharp
// 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

```csharp
// 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

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

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

#### Domains

```csharp
// 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>:

```csharp
@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>:

```csharp
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

```csharp
// 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
