2015-02-03 5 views
1

Я использую MVCSitemapProvider by Maarten Balliauw с Ninject DI в MVC4. Являясь крупномасштабным веб-приложением, перечисление над записями, чтобы генерировать учетные записи xml сайта, составляет 70% времени загрузки страницы. Для этой цели я пошел на использование новых файлов Sitemap для каждого поставщика динамического узла уровня n.Как связать файл дочернего сайта-карты с родительской картой сайта в ASP.NET MVC4 с помощью MVCSitemapProvider?

<mvcSiteMap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-4.0" xsi:schemaLocation="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-4.0 MvcSiteMapSchema.xsd"> 
    <mvcSiteMapNode title="$resources:SiteMapLocalizations,HomeTitle" description="$resources:SiteMapLocalizations,HomeDescription" controller="Controller1" action="Home" changeFrequency="Always" updatePriority="Normal" metaRobotsValues="index follow noodp noydir"><mvcSiteMapNode title="$resources:SiteMapLocalizations,AboutTitle" controller="ConsumerWeb" action="Aboutus"/> 
    <mvcSiteMapNode title="Sitemap" controller="Consumer1" action="SiteMap"/><mvcSiteMapNode title=" " action="Action3" controller="Consumer2" dynamicNodeProvider="Comp.Controller.Utility.NinjectModules.PeopleBySpecDynamicNodeProvider, Comp.Controller.Utility" /> 
    <mvcSiteMapNode title="" siteMapFile="~/Mvc2.sitemap"/> 
    </mvcSiteMapNode> 
    </mvcSiteMap> 

Но, похоже, что это не сработало. Для localhost: XXXX/sitemap.xml дочерние узлы из Mvc2.sitemap не загружаются.

ответ

0

siteMapFile не является допустимым атрибутом XML в MvcSiteMapProvider (хотя вы можете использовать его как пользовательский атрибут), поэтому я не уверен, какой проводник вы выполняете для этого. Но в нижней строке есть нет функции, которая загружает «файлы детской карты сайта», и даже если бы это было так, это не помогло бы с вашей проблемой, потому что все узлы сразу загружаются в память. Реально на среднем сервере существует верхний предел около 10 000 - 15 000 узлов.

Проблема, которую вы описываете, является известной проблемой. В issue #258 есть несколько советов, которые могут или не помогут.

Мы работаем с new XML sitemap implementation, который позволит вам подключить файл Sitemap XML напрямую к источнику данных, который можно использовать для обхода этой проблемы (по крайней мере, в отношении XML-карты сайта). Эта реализация основана на потоках и имеет подкачку, которая может быть привязана непосредственно к источнику данных и будет плавно переходить на несколько таблиц, поэтому она очень эффективна. Однако, несмотря на то, что есть рабочий прототип, еще некоторое время от него делается в выпуск.

Если вам это нужно раньше, чем позже, вы можете взять прототип от this branch.

Вам понадобится код, чтобы подключить его к вашему приложению (это может быть изменено для официального выпуска). Я создал demo project here.

Application_Start

var registrar = new MvcSiteMapProvider.Web.Routing.XmlSitemapFeedRouteRegistrar(); 
registrar.RegisterRoutes(RouteTable.Routes, "XmlSitemap2"); 

XmlSitemap2Controller

using MvcSiteMapProvider.IO; 
using MvcSiteMapProvider.Web.Mvc; 
using MvcSiteMapProvider.Xml.Sitemap.Configuration; 
using System.Web.Mvc; 

public class XmlSitemap2Controller : Controller 
{ 
    private readonly IXmlSitemapFeedResultFactory xmlSitemapFeedResultFactory; 

    public XmlSitemap2Controller() 
    { 
     var builder = new XmlSitemapFeedStrategyBuilder(); 

     var xmlSitemapFeedStrategy = builder 
      .SetupXmlSitemapProviderScan(scan => scan.IncludeAssembly(this.GetType().Assembly)) 
      .AddNamedFeed("default", feed => feed.WithMaximumPageSize(5000).WithContent(content => content.Image().Video())) 
      .Create(); 

     var outputCompressor = new HttpResponseStreamCompressor(); 

     this.xmlSitemapFeedResultFactory = new XmlSitemapFeedResultFactory(xmlSitemapFeedStrategy, outputCompressor); 
    } 

    public ActionResult Index(int page = 0, string feedName = "") 
    { 
     var name = string.IsNullOrEmpty(feedName) ? "default" : feedName; 
     return this.xmlSitemapFeedResultFactory.Create(page, name); 
    } 
} 

IXmlSiteMapProvider

И вам потребуется 1 или более IXmlSitemapProvider реализации. Для удобства существует базовый класс XmlSiteMapProviderBase. Они похожи на создание контроллеров в MVC.

using MvcSiteMapProvider.Xml.Sitemap; 
using MvcSiteMapProvider.Xml.Sitemap.Specialized; 
using System; 
using System.Linq; 

public class CategoriesXmlSitemapProvider : XmlSitemapProviderBase, IDisposable 
{ 
    private EntityFramework.MyEntityContext db = new EntityFramework.MyEntityContext(); 

    // This is optional. Don't override it if you don't want to use last modified date. 
    public override DateTime GetLastModifiedDate(string feedName, int skip, int take) 
    { 
     // Get the latest date in the specified page 
     return db.Category.OrderBy(x => x.Id).Skip(skip).Take(take).Max(c => c.LastUpdated); 
    } 

    public override int GetTotalRecordCount(string feedName) 
    { 
     // Get the total record count for all pages 
     return db.Category.Count(); 
    } 

    public override void GetUrlEntries(IUrlEntryHelper helper) 
    { 
     // Do not call ToList() on the query. The idea is that we want to force 
     // EntityFramework to use a DataReader rather than loading all of the data 
     // at once into RAM. 
     var categories = db.Category 
      .OrderBy(x => x.Id) 
      .Skip(helper.Skip) 
      .Take(helper.Take); 

     foreach (var category in categories) 
     { 
      var entry = helper.BuildUrlEntry(string.Format("~/Category/{0}", category.Id)) 
       .WithLastModifiedDate(category.LastUpdated) 
       .WithChangeFrequency(MvcSiteMapProvider.ChangeFrequency.Daily) 
       .AddContent(content => content.Image(string.Format("~/images/category-image-{0}.jpg", category.Id)).WithCaption(category.Name)); 

      helper.SendUrlEntry(entry); 
     } 
    } 

    public void Dispose() 
    { 
     db.Dispose(); 
    } 
} 

Обратите внимание, что в настоящее время не IXmlSiteMapProvider реализация, которая считывает узлы от значения по умолчанию (или любой другой) SiteMap, но создавая один подобен тому, как показано выше, за исключением того, что запрос к SiteMap для узлов вместо база данных для записей.

В качестве альтернативы вы можете использовать сторонний XML-файл Sitemap. Хотя, почти все они настроены немасштабируемым способом для больших сайтов, и большинство из них оставляют это для вас, чтобы обрабатывать пейджинг. Если они не передают узлы, они не будут реально масштабироваться более чем на несколько тысяч URL-адресов.

Другие детали, которые вам могут потребоваться, это использовать технику forcing a match, чтобы уменьшить общее количество узлов в SiteMap. Если вы используете HTML-помощники Menu и/или SiteMap, вам нужно будет оставить все ваши узлы высокого уровня в одиночку. Но любой узел, который не появляется ни в одном, является хорошим кандидатом для этого. Реально, почти любой сайт, управляемый данными, может быть сведен к нескольким десяткам узлов с использованием этого метода, но имейте в виду, что каждый узел, который вынужден сопоставлять несколько маршрутов в SiteMap, означает, что отдельные URL-записи должны быть добавлены в карту XML-данных ,

+0

Я предположил, что вы можете разрешать те атрибуты, которые имеет карта сайта по умолчанию, как в [здесь] (https://msdn.microsoft.com/en-us/library/ms178426 (v = vs.140) .aspx) , Спасибо за ссылки. Я попытаюсь использовать это приложение. FYI, я хочу иметь структуру, такую ​​как [сайт сайта practo.com] (https://www.practo.com/sitemap.xml). Вы увидите, что они уменьшают загрузку страницы, используя расположение URL-адресов для самих файлов Sitemap. И если вы будете следовать одной из ссылок, вы увидите, что их те, кто несет вес сайта, имеют многочисленные узлы. Хотя, я не уверен, что они динамичны по своей природе или нет. – devP

+0

ОК, я думаю, что неправильно понял. MvcSiteMapProvider в первую очередь предназначен для навигации по сайту, и по умолчанию он добавляет простую XML-карту для поисковых систем, которая считывает узлы из навигации SiteMap. Но если вам не нужны функции навигации, вы можете использовать прототип, как показано выше, и он автоматически разбивается и создает «дочерний файл» в значении «WithMaximumPageSize». Но FYI использует потоки выгружаемых данных, а не файлы. Пока вы не помещаете какие-либо HTML-помощники в свои представления, функции навигации не будут использоваться, но в настоящее время нет возможности полностью их отключить. – NightOwl888

+0

Другими словами, если вы не используете навигационные функции, вам нужно сохранить файл Mvc.sitemap, но вам не нужно вставлять в него какие-либо узлы, кроме корневого узла. Вы также можете проигнорировать ссылку выше о «принуждении к совпадению» и совете о том, как вытащить узлы из SiteMap навигации, потому что это не относится к вашему делу. Но примеры кода действительно применимы. – NightOwl888