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.Data
orApp.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
Data
to contain what should be shownA simple
foreach
can be used to loop through the dataThe
Data
returnsIEntity
objects but we needdynamic
objects so we can do things like@person.FullName
, so we useAsList
which wraps the items insideData
Now 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
Default
stream (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 theDefault
stream 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