Asp.net mvc Can';无法在MvcSiteMap视图中访问ViewData
我正在构建一个相当大的MVC项目,我在查看数据时遇到了一些问题。我有一个相当复杂的模型结构。我不想用简单的显示数据“polute”我的模型,但我想要强类型的数据,所以我写了几个简单的类:Asp.net mvc Can';无法在MvcSiteMap视图中访问ViewData,asp.net-mvc,viewdata,mvcsitemapprovider,asp.net-mvc-5.1,Asp.net Mvc,Viewdata,Mvcsitemapprovider,Asp.net Mvc 5.1,我正在构建一个相当大的MVC项目,我在查看数据时遇到了一些问题。我有一个相当复杂的模型结构。我不想用简单的显示数据“polute”我的模型,但我想要强类型的数据,所以我写了几个简单的类: public class GeneralViewData { private static string Id = "GeneralViewData"; public string PageTitle { get; set; } public bool ShowGuestMenu {
public class GeneralViewData
{
private static string Id = "GeneralViewData";
public string PageTitle { get; set; }
public bool ShowGuestMenu { get; set; }
public string CurrentUserName { get; set; }
public bool ShowOrganisationAdminMenu { get; set; }
protected GeneralViewData() { }
public static GeneralViewData Retrieve(ViewDataDictionary viewDataDictionary)
{
object viewData = viewDataDictionary[Id];
if (viewData == null) return Initiate(viewDataDictionary);
return (GeneralViewData)viewData;
}
private static GeneralViewData Initiate(ViewDataDictionary viewDataDictionary)
{
GeneralViewData viewData = new GeneralViewData();
viewDataDictionary[Id] = viewData;
return viewData;
}
}
因此,无论您在何处访问ViewData,都可以轻松获取模型并使用以下工具进行访问:
var generalViewData = GeneralViewData.Retrieve(ViewData);
这在大多数网站上都非常有效,但是我在MVCSiteMapProvider的视图方面遇到了问题。另外,sitemapprovider不传递主视图数据,而是将新数据传递给局部视图
我需要一种方法来让MVCSiteMapProvider将完整的视图数据传递给它的视图,或者通过将GeneralViewData实例存储到其他地方来解决这个问题。我一直在绞尽脑汁想办法解决这个问题,所以我对任何事情都持开放态度。选项1
您可以使用,但由于您的节点是菜单的一部分,因此您必须在每个控制器操作方法中都这样做
选项2
要使其在全局范围内工作,而不向每个控制器操作添加SiteMapTitleAttribute,还可以在应用程序\u PostAuthorizerRequest事件中显式设置标题
protected void Application_PostAuthorizeRequest(object sender, EventArgs eventArgs)
{
var user = HttpContext.Current.User;
if (user.Identity.IsAuthenticated)
{
var accountNode = MvcSiteMapProvider.SiteMaps.Current.FindSiteMapNodeFromKey("MyAccount");
if (accountNode != null)
{
accountNode.Title = "Hello, " + user.Identity.Name;
}
}
}
这假设您的帐户节点配置了一个值为“MyAccount”的显式密钥集
选项#3
更简洁的方法可能是使用添加一个类,该类可以检索当前用户名和其他属性
如果在上面的Application_PostAuthorizerRequest事件中设置对象,则可能会使用具有静态属性的现有对象
但是,一种更为集成的方法是使用[IDynamicNodeProvider]或IsItemaNodeProvider来提供自定义对象。请注意,如果您这样做,您将需要使用具有从当前请求检索数据(而不是存储数据)的属性/方法的对象,因为此对象将在站点地图的所有用户之间共享
然后,可以自定义MvcSiteMapProvider显示模板,以便在存在自定义对象时在适当的节点上显示此数据
选项4
通过实现和/或如上所述更好地将您的模型与ASP.NET集成,然后您可以将您的配置文件数据添加到自定义IPrincipal和/或IIdentity实现中,以便通过HttpContext对象全局可用
一旦数据在全球范围内可用,您就可以直接从视图中访问它。然后您可以自定义SiteMapNodeModel显示模板,以便在适当的时候显示数据
@model MvcSiteMapProvider.Web.Html.Models.SiteMapNodeModel
@using System.Web.Mvc.Html
@using MvcSiteMapProvider.Web.Html.Models
@* Fix the title for the MyAccount Node *@
var title = Model.Title;
if (Model.Key == "MyAccount")
{
title = "Hello, " + (User as CustomPrincipal).CurrentUserName;
}
@if (Model.IsCurrentNode && Model.SourceMetadata["HtmlHelper"].ToString() != "MvcSiteMapProvider.Web.Html.MenuHelper") {
<text>@title</text>
} else if (Model.IsClickable) {
if (string.IsNullOrEmpty(Model.Description))
{
<a href="@Model.Url">@title</a>
}
else
{
<a href="@Model.Url" title="@Model.Description">@title</a>
}
} else {
<text>@title</text>
}
@model mvcsitemprovider.Web.Html.Models.SiteMapNodeModel
@使用System.Web.Mvc.Html
@使用MvcSiteMapProvider.Web.Html.Models
@*修复MyAccount节点的标题*@
var title=Model.title;
如果(Model.Key==“MyAccount”)
{
title=“Hello,”+(用户作为CustomPrincipal).CurrentUserName;
}
@如果(Model.IsCurrentNode&&Model.SourceMetadata[“HtmlHelper”].ToString()!=“MvcSiteMapProvider.Web.Html.MenuHelper”){
@头衔
}else if(Model.isclick){
if(string.IsNullOrEmpty(Model.Description))
{
}
其他的
{
}
}否则{
@头衔
}
本例假设您已将帐户节点的键属性/属性显式设置为“MyAccount”
我还建议您为“ShowGuestMenu”和“ShowOrganizationAdminMenu”创建一个ASP.NET角色,并结合使用AuthorizeAttribute来控制子菜单的可见性,而不是使用布尔值。如果您希望用户能够打开和关闭菜单,我建议您按照自己的方式进行操作。在这种情况下,我建议使用,而不是通过更改显示模板来控制可见性。我不确定您为什么需要将数据传递到MvcSiteMapProvider视图,是否调用菜单()在_布局页面中?在本例中,我希望在菜单中显示当前用户名,而不是特定页面(帐户页面)的页面标题。我想完全绕过视图,只需输入一个静态占位符,并使用客户端脚本输入正确的文本,但如果可能的话,我想在服务器端完成。您可以将GeneralViewData类作为属性添加到MenuHelperModel中吗?您可以在构造函数中弹出这些值,它们应该可用于MvcSiteMapHelper模板。我没有尝试过这个,只是一个想法。或者,当用户登录时,将这些值添加到您的身份验证票证/会话中。