DotnetSitemapGenerator 1.0.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package DotnetSitemapGenerator --version 1.0.1
NuGet\Install-Package DotnetSitemapGenerator -Version 1.0.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DotnetSitemapGenerator" Version="1.0.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add DotnetSitemapGenerator --version 1.0.1
#r "nuget: DotnetSitemapGenerator, 1.0.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install DotnetSitemapGenerator as a Cake Addin
#addin nuget:?package=DotnetSitemapGenerator&version=1.0.1

// Install DotnetSitemapGenerator as a Cake Tool
#tool nuget:?package=DotnetSitemapGenerator&version=1.0.1

Nuget Build, Test, and Deploy

DotnetSitemapGenerator

A minimalist library for creating sitemap files inside ASP.NET Core applications and generating sitemap.xml files.

DotnetSitemapGenerator lets you create sitemap files inside action methods without any configuration. It also supports generating sitemap index files. Since you are using regular action methods you can take advantage of caching and routing available in the framework.

Advantages of DotnetSitemapGenerator

This builds upon SimpleMvcSitemap by uhaciogullari by allowing the generator to save to a physical .xml file directly with additional testing. Also this project is being actively developed and used in production applications, and upgraded to use updated dotnet features and language versions.

Table of contents

<a id="installation">Installation</a>

Install the NuGet package on your MVC project.

<a id="examples">Examples</a>

You can use SitemapProvider class to create sitemap files inside any action method. You don't even have to provide absolute URLs, DotnetSitemapGenerator can generate them from relative URLs. Here's an example:

public class SitemapController : Controller
{
    public ActionResult Index()
    {
        List<SitemapNode> nodes = new List<SitemapNode>
        {
            new SitemapNode(Url.Action("Index","Home")),
            new SitemapNode(Url.Action("About","Home")),
            //other nodes
        };

        return new SitemapProvider().CreateSitemap(new SitemapModel(nodes));
    }
}

SitemapNode class also lets you specify the optional attributes:

new SitemapNode(Url.Action("Index", "Home"))
{
    ChangeFrequency = ChangeFrequency.Weekly,
    LastModificationDate = DateTime.UtcNow.ToLocalTime(),
    Priority = 0.8M
}

<a id="serializing-to-a-file">Serializing Sitemap to a File</a>

To serialize a sitemap directly to a file this is done slightly differently than using the controller as you use the XMLSerializer directly.

IXmlSerializer sitemapProvider = new XmlSerializer(); // Instantiate a new serializer

// Add all your mappings to this list
List<SitemapNode> nodes = new() { 
    new($"https://yoursite.com/homepage") 
    { 
        LastModificationDate = newDateTime.ToLocalTime(), 
        ChangeFrequency = ChangeFrequency.Daily, 
        Priority = 1.0M 
    }
};

// second parameter xmlSavePath is the path to where you want to save your file, often "sitemap.xml"
// third parameter (true in this case) is used to mark whether the outputed xml file should be 
// formatted in a way that it is easily readable by human eyes which is helpful with visual validation
sitemapProvider.Serialize(new SitemapModel(nodes), xmlSavePath, true);

<a id="sitemap-index-files">Sitemap Index Files</a>

Sitemap files must have no more than 50,000 URLs and must be no larger then 50MB as stated in the protocol. If you think your sitemap file can exceed these limits you should create a sitemap index file. If you have a logical seperation, you can create an index manually.

List<SitemapIndexNode> sitemapIndexNodes = new List<SitemapIndexNode>
{
   new SitemapIndexNode(Url.Action("Categories","Sitemap")),
   new SitemapIndexNode(Url.Action("Products","Sitemap"))
};

return new SitemapProvider().CreateSitemapIndex(new SitemapIndexModel(sitemapIndexNodes));

If you are dealing with dynamic data and you are retrieving the data using a LINQ provider, DotnetSitemapGenerator can handle the paging for you. A regular sitemap will be created if you don't have more nodes than the sitemap size.

Generating sitemap index files

This requires a little configuration:

public class ProductSitemapIndexConfiguration : SitemapIndexConfiguration<Product>
{
    private readonly IUrlHelper urlHelper;

    public ProductSitemapIndexConfiguration(IQueryable<Product> dataSource, int? currentPage, IUrlHelper urlHelper)
        : base(dataSource,currentPage)
    {
        this.urlHelper = urlHelper;
    }

    public override SitemapIndexNode CreateSitemapIndexNode(int currentPage)
    {
        return new SitemapIndexNode(urlHelper.RouteUrl("ProductSitemap", new { currentPage }));
    }

    public override SitemapNode CreateNode(Product source)
    {
        return new SitemapNode(urlHelper.RouteUrl("Product", new { id = source.Id }));
    }
}

Then you can create the sitemap file or the index file within a single action method.

public ActionResult Products(int? currentPage)
{
    var dataSource = products.Where(item => item.Status == ProductStatus.Active);
    var productSitemapIndexConfiguration = new ProductSitemapIndexConfiguration(dataSource, currentPage, Url);
    return new DynamicSitemapIndexProvider().CreateSitemapIndex(new SitemapProvider(), productSitemapIndexConfiguration);
}

<a id="datetime-format">DateTime Format</a>

You should convert your DateTime values to local time. Universal time format generated by .NET is not accepted by Google. You can use .ToLocalTime() method to do the conversion.

<a id="google-sitemap-extensions">Google Sitemap Extensions</a>

You can use Google's sitemap extensions to provide detailed information about specific content types like images, videos, news or alternate language pages. You can still use relative URLs for any of the additional URLs.

<a id="images">Images</a>

using DotnetSitemapGenerator.Images;

new SitemapNode(Url.Action("Display", "Product"))
{
    Images = new List<SitemapImage>
    {
        new SitemapImage(Url.Action("Image","Product", new {id = 1})),
        new SitemapImage(Url.Action("Image","Product", new {id = 2}))
    }
}

<a id="videos">Videos</a>

By version 4, multiple videos are supported. Start using Videos property if you are upgrading from v3 to v4.

using DotnetSitemapGenerator.Videos;

new SitemapNode("http://www.example.com/videos/some_video_landing_page.html")
{
    Videos = new List<SitemapVideo>
    { 
        new SitemapVideo(title: "Grilling steaks for summer",
                         description: "Alkis shows you how to get perfectly done steaks every time",
                         thumbnailUrl: "http://www.example.com/thumbs/123.jpg", 
                         contentUrl: "http://www.example.com/video123.flv")
    }
}

<a id="news">News</a>

using DotnetSitemapGenerator.News;

new SitemapNode("http://www.example.org/business/article55.html")
{
    News = new SitemapNews(newsPublication: new NewsPublication(name: "The Example Times", language: "en"),
                           publicationDate: new DateTime(2014, 11, 5, 0, 0, 0, DateTimeKind.Utc),
                           title: "Companies A, B in Merger Talks")
}

<a id="translations">Alternate language pages</a>

using DotnetSitemapGenerator.Translations;

new SitemapNode("abc")
{
    Translations = new List<SitemapPageTranslation>
    {
        new SitemapPageTranslation("http://www.example.com/deutsch/", "de"),
		new SitemapPageTranslation("http://www.example.com/english/", "en")
    }
}

<a id="style-sheets">XSL Style Sheets</a>

DotnetSitemapGenerator supports XSL style sheets by version 3. Keep in mind that XML stylesheets are subjected to the same origin checks.

using DotnetSitemapGenerator.StyleSheets;

new SitemapModel(new List<SitemapNode> { new SitemapNode("abc") })
{
    StyleSheets = new List<XmlStyleSheet>
    {
        new XmlStyleSheet("/sitemap.xsl")
    }
};

You can see how you can utilize multiple XSL style sheets in this tutorial.

<a id="base-url">Custom Base URL</a>

DotnetSitemapGenerator can generate absolute URLs from the relative URLs using the HTTP request context. If you want to customize this behaviour, you can implement IBaseUrlProvider interface and pass it to the SitemapProvider class.

public class BaseUrlProvider : IBaseUrlProvider
{
    public Uri BaseUrl => new Uri("http://example.com");
}

var sitemapProvider = new SitemapProvider(new BaseUrlProvider());

<a id="di">Unit Testing and Dependency Injection</a>

SitemapProvider class implements the ISitemapProvider interface which can be injected to your controllers and be replaced with test doubles. All methods are thread safe so they can be used with singleton life cycle.

public class SitemapController : Controller
{
    private readonly ISitemapProvider _sitemapProvider;

    public SitemapController(ISitemapProvider sitemapProvider)
    {
        _sitemapProvider = sitemapProvider;
    }
	
    //action methods
}

<a id="license">License</a>

DotnetSitemapGenerator is licensed under MIT License. Refer to license file for more information.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp1.0 was computed.  netcoreapp1.1 was computed.  netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard1.6 is compatible.  netstandard2.0 was computed.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen30 was computed.  tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.4 3,940 9/2/2022
1.0.3 461 8/30/2022
1.0.2 462 8/30/2022
1.0.1 470 8/25/2022
1.0.0 417 8/25/2022