Guide for Using DataSources in your C# Code
All data comes from DataSources. Either because something prepared the DataSources for your code, or because your code explicitly requested a DataSource from the API.
Some DataSources are prepared and always available in Razor and WebApi, like
Data,App.DataorApp.Query["QueryName"]And you can also get other DataSources in C# code, like
Kit.Data.GetSource<EntityTypeFilter>()
Step 1: Use a DataSource
This is a basic example of an Employees Razor Template.
It uses the Data DataSource which is always available in Razor and WebApi.
For some magical reasons we'll explain later, the Data is a DataSource which in this case provides all the Employees which should be shown.
@foreach(var person in AsList(Data)) {
<li>@person.FullName (@person.Function)</li>
}
This demonstrates
Some magic in the background prepared
Datato contain what should be shownA simple
foreachcan be used to loop through the dataThe
DatareturnsIEntityobjects but we needdynamicobjects so we can do things like@person.FullName, so we useAsListwhich wraps the items insideDataNow we can just output the values as needed, like
@person.FullName
We have an rich series of Razor tutorials. You should really check them out 👍.
Step 2: Understanding Prepared Data
You will usually use DataSource objects in these common cases in both Razor and Custom WebApi:
The Data object is a DataSource. It always has a
Defaultstream (Data["Default"]). Sotemites it has other streams likeData["ListContent"]orData["Categories"]etc.The App.Data is a DataSource providing a stream for each content-type in this app, like
App.Data["BlogPost"]orApp.Data["Tag"]Every App.Query[...] is a DataSource. In the query you define which DataStreams it has. Eg.
App.Query["SortedTags"]would be a DataSource and typically theDefaultstream would contain all these tags.A query is actually a set DataSources doing one operation and passing it on to the next DataSource
Step 3: Use The Data As Prepared
In your code you'll usually work with these three sources which have been prepared for you:
If all you want is to loop through various lists already available, you'll usually work with AsList like this:
@foreach(var item in AsList(Data)) {
<li>@item.Title</li>
}
Note that AsList(Data) is a Shorthand for AsList(Data.List) or AsList(Data["Default"].List):
@foreach(var item in AsList(Data["Default"].List)) {
<li>@item.Title</li>
}
If your data-source Data, App.Data or App.Query["QueryName"] has more than one stream, you would do this:
@foreach(var item in AsList(App.Data["Categories"])) {
<li>@item.CategoryName</li>
}
Step 4: Create DataSource Objects in C#/Razor Code
Sometimes you want to have full control over what a DataSource does or what parameters it's using. This is easy:
// A source which can filter by Content-Type (EntityType)
var allAuthors = Kit.Data.GetSource<ToSic.Eav.DataSources.EntityTypeFilter>(
attach: App.Data, // Use the apps data as input
parameters: new { TypeName = "Author" } // tell it to filter by "Author"
);
// access the data and automatically apply the filter/config
var authors = allAuthors.List;
👉 Also read Set Parameters for DataSource Objects in C#/Razor Code
Tip
2sxc 16 uses a new Kit.Data.GetSource(...) to get DataSources.
Older code used CreateSource(...) which is still available, but deprecated.
The new method is more powerful and we'll slowly migrate to that API only
Step 5: Create a Query in Code by Attaching Data sources
What the VisualQuery designer does is configure how DataSources are attached, mapping their in/out streams and adding parameters.
You can also do this in code, but it's fairly advanced. You would usually want to do this, if you want to use a filter or something, but need to provide parameters which aren't available in the VisualQuery Designer. Here's a simple example:
using ToSic.Eav.DataSources;
// A source which can filter by Content-Type (EntityType)
var allAuthors = Kit.Data.GetSource<EntityTypeFilter>(
attach: App.Data, // Use the apps data as input
parameters: new { TypeName = "Author" } // tell it to filter by "Author"
);
// Sort by FullName
var sortedAuthors = Kit.Data.GetSource<ValueSort>(attach: allAuthors,
parameters: { Attributes = "FullName" });
// Sort by FullName descending
var sortedAuthorsDesc = Kit.Data.GetSource<ValueSort>(attach: allAuthors,
parameters: { Attributes = "FullName", Directions = "desc" });
// Sort by 2 fields
var sortedAuthorsMult = Kit.Data.GetSource<ValueSort>(attach: allAuthors,
parameters: { Attributes = "Website,FullName", Directions = "asc, desc" });
// sort by internal EntityId
var sortedAuthorsById = Kit.Data.GetSource<ValueSort>(attach: allAuthors,
parameters: { Attributes = "EntityId" });
The most important thing to notice is that each additional data-source uses the first allAuthors DataSource as the default upstream DataSource.
So when these sort/filter or do something, they will only receive the data already filtered by the allAuthors.
Read also
- Data Sources
- Data Streams
- Dynamic Code CreateSource<T>(...)
- .net API
- Demo-App showing some coding of DataSources
- Blog about creating your own data-source
History
- Introduced in 2sxc 04.00
- Changed API in 2sxc 16 to use
Kit.Data.GetSource(...)instead ofCreateSource(...) - Changed API ni 2sxc 16 to use
parameters:at construction time instead of setting variables on the object