Introduction
In this article, we will walk through the process of creating dynamically loading cards that pull content from your database and display it in a neat two-column layout. This is an efficient way to present feature-based content while maintaining a clean and SEO-friendly user interface.
Objective
Our goal is to display articles in dynamically generated cards that are styled in a way that offers a great user experience, improves SEO, and is easy to maintain. Each article will contain a title, description, icon, and an SEO-friendly URL.
Key Features
SEO-friendly URLs: Each article will have a clean, readable URL.
Dynamic Loading: Articles are loaded from the database in real-time.
Left and Right Column Layout: Articles will be grouped into pairs, displayed in two columns.
Alternating Background Colors: Grey backgrounds will alternate for visual appeal.
Handling Odd Number of Articles: If there is an odd number of articles, the last row will only contain a left card.
Components Used
ASP.NET Repeater Control: Used to display the articles dynamically.
Database Query: A SQL query is used to fetch active articles from the database.
CSS Styling: Custom styles are applied to alternate the background colors for left and right cards.
Step-by-Step Implementation
1. ASP.NET Repeater Control
The Repeater control is responsible for displaying each article. We create a dynamic structure using ItemTemplate, which allows us to render each article's content into styled cards.
<asp:Repeater ID="rptFeatures" runat="server">
<ItemTemplate>
<div class="col-sm-12 col-xs-12 nopad">
<!-- LEFT CARD -->
<div class='col-sm-6 col-xs-12 nopad <%# GetLeftStyle(Container.ItemIndex) %>'>
<div class="abc">
<div class="col-sm-2 col-xs-3 nopad top_pd">
<div class='product-icon <%# Eval("Left.Icon") %>'></div>
</div>
<div class="col-sm-10 col-xs-8 nopad">
<div class="heads_h2 heads_h2_resp"><%# Eval("Left.Heading") %></div>
<p class="paras paras_resp"><%# Eval("Left.Summary") %></p>
<div class="button read_more">
<a href='<%# Eval("Left.Link") %>'>Read APIs <span class="font_aws"></span></a>
</div>
<div class="blnk_sp"> </div>
</div>
</div>
</div>
<!-- RIGHT CARD -->
<asp:Panel runat="server" Visible='<%# Eval("Right") != null %>'>
<div class='col-sm-6 col-xs-12 nopad <%# GetRightStyle(Container.ItemIndex) %>'>
<div class="abc">
<div class="col-sm-2 col-xs-3 nopad top_pd">
<div class='product-icon <%# Eval("Right.Icon") %>'></div>
</div>
<div class="col-sm-10 col-xs-8 nopad">
<div class="heads_h2 heads_h2_resp"><%# Eval("Right.Heading") %></div>
<p class="paras paras_resp"><%# Eval("Right.Summary") %></p>
<div class="button read_more">
<a href='<%# Eval("Right.Link") %>'>Read APIs <span class="font_aws"></span></a>
</div>
<div class="blnk_sp"> </div>
</div>
</div>
</div>
</asp:Panel>
</div>
</ItemTemplate>
</asp:Repeater>
2. Database Query and Feature Retrieval
The code retrieves active articles from the database. These articles include a title, description, and icon.
string SQL = ConfigurationManager.ConnectionStrings["MainPortal"].ToString();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadFeatures();
}
}
protected void LoadFeatures()
{
var features = new List<FeatureVM>();
string query = @"
SELECT DisplayOrder, FeatureName, FeatureText, FeatureIcon
FROM FeatureCatalog
WHERE IsEnabled = 1
ORDER BY DisplayOrder
";
DataSet ds = SqlHelper.ExecuteDataset(SQL, CommandType.Text, query);
foreach (DataRow row in ds.Tables[0].Rows)
{
string name = row["FeatureName"].ToString().Trim();
features.Add(new FeatureVM
{
Heading = name,
Summary = row["FeatureText"].ToString(),
Icon = row["FeatureIcon"].ToString(),
Link = "services/" + MakeSlug(name)
});
}
var pairedRows = new List<FeatureRowVM>();
for (int i = 0; i < features.Count; i += 2)
{
pairedRows.Add(new FeatureRowVM
{
Left = features[i],
Right = (i + 1 < features.Count) ? features[i + 1] : null
});
}
rptFeatures.DataSource = pairedRows;
rptFeatures.DataBind();
}
3. View Models
We use FeatureVM for individual feature data and FeatureRowVM to group features in pairs.
public class FeatureRowVM
{
public FeatureVM Left { get; set; }
public FeatureVM Right { get; set; }
}
public class FeatureVM
{
public string Heading { get; set; }
public string Summary { get; set; }
public string Link { get; set; }
public string Icon { get; set; }
}
4. Styling Logic
We alternate background colors for visual rhythm using the GetLeftStyle and GetRightStyle methods.
public string GetLeftStyle(int rowIndex)
{
int pos = rowIndex * 2 + 1;
return IsGreyBox(pos) ? "greybg" : "grey_box";
}
public string GetRightStyle(int rowIndex)
{
int pos = rowIndex * 2 + 2;
return IsGreyBox(pos) ? "greybg white_box" : "";
}
private bool IsGreyBox(int pos)
{
int mod = (pos - 1) % 4;
return mod == 0 || mod == 3;
}
5. SEO-Friendly URL Generator
We ensure SEO-friendly URLs by generating slugs from article names. The MakeSlug function converts feature names into lowercase, removes special characters, and replaces spaces with hyphens.
public static string MakeSlug(string text)
{
if (string.IsNullOrEmpty(text))
return "";
text = text.ToLowerInvariant();
text = Regex.Replace(text, @"&", "and");
text = Regex.Replace(text, @"[^a-z0-9\s-]", "");
text = Regex.Replace(text, @"\s+", "-");
text = Regex.Replace(text, @"-+", "-");
return text.Trim('-');
}
Conclusion
By following the steps outlined above, we have successfully created dynamic article-style cards that load from the database and display in a clean two-column format. This solution provides:
SEO-friendly URLs: Articles are accessible via readable URLs.
Consistent UI: Alternating background colors enhance readability.
Fast Loading: The use of the Repeater control ensures smooth performance.
Easy CMS Control: The system allows for easy article management directly from the database.
This setup is ideal for CMS-based websites or feature-focused web applications where content is frequently updated.
Summary
This implementation demonstrates how to build dynamic two-column feature cards in ASP.NET using a Repeater control, database-driven content, paired view models, alternating styling logic, and SEO-friendly slug generation. The approach ensures maintainability, performance, and a clean user interface suitable for content-driven applications.