LifeAct
@LifeAct
Создаем и раскручиваем, не ставим на конвейер

Как всё-таки сделать динамическую sitemap.xml для сайта?

Всем привет!

Есть сайт с разными категориями записей типа А и еще тремя типами записей. Записи регулярно добавляются, хочу сделать sitemap.xml, ту, что полезна для SEO.

Пересмотрел массу статей, вот никак не могу понять, как сделать эту карту сайта, везде обрывки примеров, либо мегасложные варианты. У кого-то есть рабочий вариант?

UP1
Реализую вариант предложенный @geeek

[NonAction]
        private IEnumerable<SitemapNode> GetSitemapNodes()
        {
            RecordManager recordsManager = new RecordManager();

            // вот так добавляются статические ноды

            //тут будут все узлы
            var nodes = new List<SitemapNode>

            {
                new SitemapNode(ControllerContext.RequestContext,
                    new {area = "", controller = "Home", action = "Index"})
                {
                    Frequency = SitemapFrequency.Monthly,
                    Priority = 0.5
                },
                new SitemapNode(ControllerContext.RequestContext,
                    new {area = "", controller = "Home", action = "About"})
                {
                    Frequency = SitemapFrequency.Monthly,
                    Priority = 0.5
                }
            };


            // а вот так динамические

            //добавим афоризмы
            var Aphorisms = recordsManager.AforismsForSitemap();   

            foreach (var item in Aphorisms)
            {
                nodes.Add(new SitemapNode(ControllerContext.RequestContext,
                    new { area = "", controller = "Record", action = "AphorismDetail", link = item })
                {
                    Frequency = SitemapFrequency.Weekly,
                    Priority = 0.8
                });
            }

            return nodes;
        }

       


        [NonAction]
        private string GetSitemapXml()
        {
            XNamespace xmlns = SitemapsNamespace;

            var nodes = GetSitemapNodes();

            var root = new XElement(xmlns + "urlset");


            foreach (var node in nodes)
            {
                root.Add(
                    new XElement(xmlns + "url",
                        new XElement(xmlns + "loc", Uri.EscapeUriString(node.Url)),
                        node.Priority == null
                            ? null
                            : new XElement(xmlns + "priority",
                                node.Priority.Value.ToString("F1", CultureInfo.InvariantCulture)),
                        node.LastModified == null
                            ? null
                            : new XElement(xmlns + "lastmod",
                                node.LastModified.Value.ToLocalTime().ToString("yyyy-MM-ddTHH:mm:sszzz")),
                        node.Frequency == null
                            ? null
                            : new XElement(xmlns + "changefreq", node.Frequency.Value.ToString().ToLowerInvariant())
                        ));
            }

            using (var ms = new MemoryStream())
            {
                using (var writer = new StreamWriter(ms, Encoding.UTF8))
                {
                    root.Save(writer);
                }

                return Encoding.UTF8.GetString(ms.ToArray());
            }
        }


//ПОЛУЧИТЬ АФФОРИЗМЫ ДЛЯ Sitemap
        public List<int> AforismsForSitemap()
        {
            if (db == null) { db = new DLL.nissanin_AFFEntities(); }

            var list = (from o in db.Records where o.Type == 1 orderby o.DateGreate descending select o.id_rec).ToList();
            return list;          
        }


В итоге работает, но не совсем корректно: aforizmus.com/sitemap.xml

как видите ссылка - aforizmus.com/Record/aphorism?item=1428

а должна быть: aforizmus.com/aphorism/1431 - это я воспользовался генератором карты сайта, он мне файл сгенерировал.

Как же привести к aforizmus.com/aphorism/1431 ?
  • Вопрос задан
  • 6240 просмотров
Решения вопроса 1
geeek
@geeek
Контроллер:

public class SeoController : Controller
    {
        private const string SitemapsNamespace = "http://www.sitemaps.org/schemas/sitemap/0.9";

        [NonAction]
        private IEnumerable<SitemapNode> GetSitemapNodes()
        {
            // вот так добавляются статические ноды
            var nodes = new List<SitemapNode>
            {
                new SitemapNode(ControllerContext.RequestContext,
                    new {area = "", controller = "Home", action = "Index"})
                {
                    Frequency = SitemapFrequency.Monthly,
                    Priority = 0.5
                },
                new SitemapNode(ControllerContext.RequestContext,
                    new {area = "", controller = "Home", action = "About"})
                {
                    Frequency = SitemapFrequency.Monthly,
                    Priority = 0.5
                }
            };
              // а вот так динамические
                var items = model.Collection.ToList();
                foreach (var item in items)
                {
                    nodes.Add(new SitemapNode(ControllerContext.RequestContext,
                        new {area = "", controller = "Home", action = "blablabla", link = item.Id})
                    {
                        Frequency = SitemapFrequency.Weekly,
                        Priority = 0.8
                    });
                }
        }

        [NonAction]
        private string GetSitemapXml()
        {
            XNamespace xmlns = SitemapsNamespace;

            var nodes = GetSitemapNodes();

            var root = new XElement(xmlns + "urlset");


            foreach (var node in nodes)
            {
                root.Add(
                    new XElement(xmlns + "url",
                        new XElement(xmlns + "loc", Uri.EscapeUriString(node.Url)),
                        node.Priority == null
                            ? null
                            : new XElement(xmlns + "priority",
                                node.Priority.Value.ToString("F1", CultureInfo.InvariantCulture)),
                        node.LastModified == null
                            ? null
                            : new XElement(xmlns + "lastmod",
                                node.LastModified.Value.ToLocalTime().ToString("yyyy-MM-ddTHH:mm:sszzz")),
                        node.Frequency == null
                            ? null
                            : new XElement(xmlns + "changefreq", node.Frequency.Value.ToString().ToLowerInvariant())
                        ));
            }

            using (var ms = new MemoryStream())
            {
                using (var writer = new StreamWriter(ms, Encoding.UTF8))
                {
                    root.Save(writer);
                }

                return Encoding.UTF8.GetString(ms.ToArray());
            }
        }

        [OutputCache(Duration = 60*60, Location = System.Web.UI.OutputCacheLocation.Any)]
        public ActionResult SitemapXml()
        {
            var content = GetSitemapXml();
            return Content(content, "application/xml", Encoding.UTF8);
        }

        [OutputCache(Duration = 60*60, Location = System.Web.UI.OutputCacheLocation.Any)]
        public FileContentResult RobotsText()
        {
            var content = new StringBuilder("User-agent: *" + Environment.NewLine);
            content.Append("Host: ").Append("www.твой-домен.ru" + Environment.NewLine);
            content.Append("Sitemap: ")
                .Append("www.твой-домен.ru")
                .Append("/sitemap.xml" + Environment.NewLine);
            return File(
                Encoding.UTF8.GetBytes(content.ToString()),
                "text/plain");
        }
    }


Модель:

public class SitemapNode
    {
        public string Url { get; set; }
        public DateTime? LastModified { get; set; }
        public SitemapFrequency? Frequency { get; set; }
        public double? Priority { get; set; }


        public SitemapNode(string url)
        {
            Url = url;
            Priority = null;
            Frequency = null;
            LastModified = null;
        }

        public SitemapNode(RequestContext request, object routeValues)
        {
            Url = GetUrl(request, new RouteValueDictionary(routeValues));
            Priority = null;
            Frequency = null;
            LastModified = null;
        }

        private string GetUrl(RequestContext request, RouteValueDictionary values)
        {
            var routes = RouteTable.Routes;
            var data = routes.GetVirtualPathForArea(request, values);

            if (data == null)
            {
                return null;
            }

            var baseUrl = request.HttpContext.Request.Url;
            var relativeUrl = data.VirtualPath;

            return request.HttpContext != null &&
                   (request.HttpContext.Request != null && baseUrl != null)
                ? new Uri(baseUrl, relativeUrl).AbsoluteUri
                : null;
        }
    }

    public enum SitemapFrequency
    {
        Never,
        Yearly,
        Monthly,
        Weekly,
        Daily,
        Hourly,
        Always
    }


В Web.config добавь в system.webServer :

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>


Ну и сами маршруты:

routes.MapRoute(
                name: "sitemap.xml",
                url: "sitemap.xml",
                defaults: new {controller = "Seo", action = "SitemapXml"}
                );

            routes.MapRoute(
                name: "robots.txt",
                url: "robots.txt",
                defaults: new {controller = "Seo", action = "RobotsText"}
                );
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@mayorovp
Комментировать
Для самописного сайта не подойдёт ни одно из готовых решений, работающих изнутри сайта. То есть либо брать какое-то решение, которое само обходит сайт и на основании этого составляет сайтмэп, либо самому писать генератор, зная внутреннюю структуру сайта.
Первый вариант плох тем, что некоторые нужные страницы могут не попасть в индекс, а некоторые ненужные, наоборот, попадут туда.
Второй вариант этих недостатков лишён.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы