It’s important that your website is able to provide its Sitemap so that it’s easier for Google Search Console to index. In this tutorial, we will learn how to automatically and dynamically create the Sitemap in .Net MVC project.
In case you don’t know what Google Search Console is, please read my previous post How To Submit Your Site To Google Search Console. Basically, it's a website from Google which indexes your site and bring it to Google search result. We will see what is a sitemap and how to implement it in your .Net Core MVC project in this post.
1. What is a Sitemap?
A sitemap, as its name can tell, is a map that leads Google to all of the pages that you think it's important in your website. A site map can be formatted in an XML file. Google, or other search engines, read this XML file to be more intelligent while crawling your website. Below is an example of how a sitemap file is like in XML format.
<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>https://www.lucasology.com/</loc> <lastmod>2020-01-01</lastmod> <changefreq>monthly</changefreq> <priority>0.8</priority> </url> </urlset>
You can manually create an XML file and add each of your website page URLs to your sitemap and publish it to the server. However, that is to tedious and it requires you to republish this sitemap again and again whenever you post a new article. So, this post will show how a Sitemap can be dynamically created using .Net Core MVC.
2. How to Dynamically Create a Sitemap using .Net Core MVC?
I will walk through all steps required to dynamically create a sitemap in .Net Core MVC project. This is a great feature especially when you have a dynamic website for news, events, articles, blog, etc. where URLs are automatically created when you add a new post.
Step 1: Create a SitemapUrl class
The purpose of this class is to create object that hold information for sitemap properties for each of the URLs in your website.
public enum ChangeFrequency { Always, Hourly, Daily, Weekly, Yearly, Never } public class SitemapUrl { public string Url { get; set; } public DateTime? Modified { get; set; } public ChangeFrequency? ChangeFrequency { get; set; } public double? Priority { get; set; } }
Step 2: Create a Sitemap Builder class
It's easier to initiate a sitemap object if we have a builder like a StringBuilder to build the sitemap. We need to use System.Xml.Linq and System.Linq namespaces for this class.
using System.Xml.Linq; using System.Linq; public class SitemapBuilder { private readonly XNamespace NS = "http://www.sitemaps.org/schemas/sitemap/0.9"; private List<SitemapUrl> _urls; public SitemapBuilder() { _urls = new List<SitemapUrl>(); } public void AddUrl(string url, DateTime? modified = null, ChangeFrequency? changeFrequency = null, double? priority = null) { _urls.Add(new SitemapUrl() { Url = url, Modified = modified, ChangeFrequency = changeFrequency, Priority = priority }); } public override string ToString() { var sitemap = new XDocument( new XDeclaration("1.0", "utf-8", "yes"), new XElement(NS + "urlset", from item in _urls select CreateItemElement(item) )); return sitemap.ToString(); } private XElement CreateItemElement(SitemapUrl url) { XElement itemElement = new XElement(NS + "url", new XElement(NS + "loc", url.Url)); if(url.Modified.HasValue) { itemElement.Add(new XElement(NS + "lastmod", url.Modified.Value.ToString("yyyy-MM-dd"))); } if(url.ChangeFrequency.HasValue) { itemElement.Add(new XElement(NS + "changefreq", url.ChangeFrequency.Value.ToString())); } if (url.Priority.HasValue) { itemElement.Add(new XElement(NS + "priority", url.Priority.Value.ToString("N1"))); } return itemElement; } }
Step 3: Create a SitemapController and a Sitemap Index view
In MVC project, you need to create a Controller for managing (get/update/delete) data and pass the data to the view. You may want to create a Business Layer and Repository also but to simplify and focus on Sitemap only, this post will just create a Controller and a View for the sitemap.
SitemapController.cs: The controller contains the logic to get all posts from the database and use SitemapBuilder to build the sitemap in XML format.
public class SitemapController : Controller { private readonly IBlogManager _blogManager; private readonly IHttpContextAccessor _httpContextAccessor; public SitemapController(IBlogManager blogerManager, IHttpContextAccessor httpContextAccessor) { _blogManager = blogerManager; _httpContextAccessor = httpContextAccessor; } public IActionResult Index() { var baseUrl = $"https://{_httpContextAccessor.HttpContext.Request.Host.Value}"; //Get All Posts from Database. var posts = _blogManager.GetPosts(null); var siteMapBuilder = new SitemapBuilder(); siteMapBuilder.AddUrl(baseUrl, modified: DateTime.UtcNow, changeFrequency: ChangeFrequency.Weekly, priority: 1.0); siteMapBuilder.AddUrl(baseUrl + "/AboutMe", modified: DateTime.UtcNow, changeFrequency: ChangeFrequency.Weekly, priority: 0.6); siteMapBuilder.AddUrl(baseUrl + "/Blog", modified: DateTime.UtcNow, changeFrequency: ChangeFrequency.Daily, priority: 0.6); //Loop each post and add it to the Sitemap foreach (var post in posts) { siteMapBuilder.AddUrl(baseUrl + "/?url=" + HttpUtility.UrlEncode(post.Content), modified: post.UpdatedOn, changeFrequency: ChangeFrequency.Yearly, priority: 1.0); } string xml = siteMapBuilder.ToString(); return Content(xml, "text/xml"); } }
Sitemap/Index.cshtml: The view is basically empty and act as a holder for the returned xml content from the Controller.
@{ ViewData["Title"] = "Sitemap"; }
Done! So now, you can navigate to [YourWebsiteHost]/Sitemap to see your brandnew sitemap which is automatically and dynamically updated everytime you have a new post. You can also modify your Controller or SitemapUrl class to dynamically update Priority or Frequency value of your sitemap. Here is how it looks like in my website:
You can then use your sitemap URL to submit it to Google Search Console. That will help you a lot regarding promoting your website on Google Search. I hope this is helpful and you can successfully implement this in your project.