4

我想在我的ASP.Net MVC 5应用程序中使用MVCSiteMapProvider。可以找到大量的资源和教程,但其中大部分都是关于基于XML的配置。使用MvcSiteMapProvider属性和属性路由

在我的应用程序属性路由已经使用,我想用属性MvcSiteMapProvider但没有足够的资源关于这种混合,我有一些问题。

例如我有像下面三个动作:

//HomeController  
    [Route(@"~/home", Name = "CustomerHomeIndex")] 
     [MvcSiteMapNode(Title = "Home Page", Key = "Home")] 
     public ActionResult Index() { 
      return View() 
     } 

//AccountController  
     [Route(@"~/account", Name = "AccountIndex")] 
     [MvcSiteMapNode(Title = "Accounts", ParentKey = "Home", Key = "AccountIndex")] 
     public ActionResult Index() { 
     // fetching records from database 
      return View(); 
     } 

     [Route(@"~/account-management/{id:int}/{domain:regex(^([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$)}", Name = "AccountDetail")] 
     [MvcSiteMapNode(Title = "Account Detail", ParentKey = "AccountIndex", Key = "AccountDetail")] 
     public ActionResult Details(string domain, int id) { 
     // fetching record from database by parameters 
      return View(); 
     } 

我还添加的SiteMapPath代码我的看法

//Details.cshtml 
    @Html.MvcSiteMap().SiteMapPath() 

但没有什么是显示结果。在我看来,它是关于preservedRouteParameters,但我找不到有关此属性路由的MvcSiteMapNode属性中使用此参数的任何内容。

其实我还有一个关于本地化的问题,我想从资源文件中获取标题,所有东西都已经存在于全局资源文件中。我读了一些关于本地化支持的内容,但它们也与基于XML的配置有关。

回答

3

默认情况下,启用XML和.NET属性的提供程序。在此配置中,根节点(没有父键的节点)必须放置在XML文件中。要在XML中没有任何配置的情况下独占使用.NET属性,您需要从配置中删除XML节点提供程序。

内部DI:

<appSettings> 
    <add key="MvcSiteMapProvider_EnableSiteMapFile" value="false"/> 
</appSettings> 

外部DI(StructureMap示例所示):

// Register the sitemap node providers 
var siteMapNodeProvider = this.For<ISiteMapNodeProvider>().Use<CompositeSiteMapNodeProvider>() 
    .EnumerableOf<ISiteMapNodeProvider>().Contains(x => 
    { 
     //Remove the XmlSiteMapNodeProvider 
     //x.Type<XmlSiteMapNodeProvider>() 
     // .Ctor<bool>("includeRootNode").Is(true) 
     // .Ctor<bool>("useNestedDynamicNodeRecursion").Is(false) 
     // .Ctor<IXmlSource>().Is(xmlSource); 
     x.Type<ReflectionSiteMapNodeProvider>() 
      .Ctor<IEnumerable<string>>("includeAssemblies").Is(includeAssembliesForScan) 
      .Ctor<IEnumerable<string>>("excludeAssemblies").Is(new string[0]); 
    }); 

您还需要确保大会与你的控制器包含在IncludeAssembliesForScan配置设置。请注意,NuGet包会自动包含您安装MvcSiteMapProvider的程序集,因此如果您的控制器都在您的主MVC项目中,则不需要触摸它。

内部DI:

<appSettings> 
    <add key="MvcSiteMapProvider_IncludeAssembliesForScan" value="MyAssembly,MyOtherAssembly"/> 
</appSettings> 

外部DI:

string[] includeAssembliesForScan = new string[] { "MyAssembly", "MyOtherAssembly" }; 

... Other code omitted ... 

// Register the sitemap node providers 
var siteMapNodeProvider = this.For<ISiteMapNodeProvider>().Use<CompositeSiteMapNodeProvider>() 
    .EnumerableOf<ISiteMapNodeProvider>().Contains(x => 
    { 
     //Remove the XmlSiteMapNodeProvider 
     //x.Type<XmlSiteMapNodeProvider>() 
     // .Ctor<bool>("includeRootNode").Is(true) 
     // .Ctor<bool>("useNestedDynamicNodeRecursion").Is(false) 
     // .Ctor<IXmlSource>().Is(xmlSource); 
     x.Type<ReflectionSiteMapNodeProvider>() 
      .Ctor<IEnumerable<string>>("includeAssemblies").Is(includeAssembliesForScan) // <- Setting is injected here 
      .Ctor<IEnumerable<string>>("excludeAssemblies").Is(new string[0]); 
    }); 

没有什么特别的,你需要做的,使其与AttributeRouting工作 - MvcSiteMapProvider自动所以只要拿起那些路由你让他们配置正确,并在MVC中工作,它应该工作。

是的,您可能确实需要为包含自定义参数的操作使用PreservedRouteParameters,如下所示。

[Route(@"~/account-management/{id:int}/{domain:regex(^([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$)}", Name = "AccountDetail")] 
[MvcSiteMapNode(Title = "Account Detail", ParentKey = "AccountIndex", Key = "AccountDetail", PreservedRouteParameters="domain,id")] 
public ActionResult Details(string domain, int id) { 
// fetching record from database by parameters 
    return View(); 
} 

在你的简单例子中,这将工作正常。但是,当嵌套级别超过第一个节点时,您需要充分认识如何正确使用preserveRouteParameters以正确使用它们。您不能使用具有相同键名且参数在同一个请求中可见的参数,因为MvcSiteMapProvider始终将当前请求中的值插入到具有匹配键名称的所有节点中。您还必须提供(子节点的)请求中的祖先节点所需的任何密钥,以便导航工作。有关完整的详细信息,请参见How to Make MvcSiteMapProvider Remember a User's Position和演示代码。

请参阅此为reading localization from an external assembly。但是请注意,从4.6版本开始,唯一可行的方法是使用外部DI容器来注入自定义的IStringLocalizer。

默认的本地化实现只能支持放入App_GlobalResources文件夹的文件。请注意,这是problematic with MVC,因为添加这些文件时的默认设置使得它们以不能从MVC访问的方式进行编译。我们目前是gathering requirements to make a new extension point,允许从其他位置配置资源。

+0

感谢您的详细解答,它非常有帮助,并添加了PreservedRouteParameters解决了我的问题。而关于本地化,我不想从外部装配本地化。我已经在App_GlobalResources文件夹中有资源文件。但在MvcSiteMapNode构造函数中查找参数TitleResourceKey并看不到。如何让MvcSiteMapNode从App.GlobalResources文件中的Resources.resx文件中读取标题? – 2014-09-08 06:26:42

+0

我试过Title =“$ resources:Resources.Resource,HomePage”但是得到了“带键的节点'Home'没有'标题'集。标题是每个节点的必填字段。错误。编辑:我将我的代码更改为Title =“$ resources:Resource,HomePage”并开始工作。谢谢你的一切 – 2014-09-08 07:28:49