我在_Layout.cshtml中使用@RenderSection(“Contextual”,false)来允许不同的视图在那里呈现它们的特定内容.有些人没有,有些则没有.
此外,我使用基于角色的安全性和ActionFilter来控制特定用户是否可以访问特定的控制器操作,从而控制我的站点上的路由.
我想做的是在我的_Layout.cshtml上提供一个@RenderSection(“Contextual”,false)部分,然后让特定页面提供对该页面有意义的任何上下文内容,并让相应的控制器处理审查是否用户可以执行操作,甚至可能看到选项存在,但我不确定我是否正确地考虑了这一点.以下是目前的情况:
现在我在我的一个Index.cshtml文件中有一个部分,如下所示:
@section Contextual { <div>@Html.ActionLink("Create New","Create")</div> <div>@Html.ActionLink("Generate Report","Report")</div> <div>@Html.ActionLink("Other Stuff","Other")</div> }
然后在我相应的控制器中,我有类似的东西:
[Authorize(Roles = "Editor")] public ActionResult Create() { // stuff }
这将按我的意愿工作(非编辑器不会创建新项目),但Create条目可供所有人查看.我可以这样做:
@section Contextual { @if (User.IsInRole("Editor")) { <div>@Html.ActionLink("Create New","Create")</div> } <div>@Html.ActionLink("Generate Report","Other")</div> }
这样做效果很好,隐藏了非编辑的创建链接,但是我已经开始关注这样做是否好处,而且我可以看到在路上我遇到的情况规则改变然后我有两个位置保持同步:控制器动作的属性和视图中的代码.
解决方法
我喜欢使用对于在控制器上填充的视图模型更明确的标志.
例如:
// on the controller viewmodel.CanCrete = User.IsInRole("Editor"); // ...snip... return View(viewmodel); }
因此,您需要将此标志添加到视图模型中,或者可能添加到视图模型的基类中.您可以创建一个Custom Action Filter的路径,将其填充到多个控制器中,或者在控制器基类中进行一些处理.
我还想定义一个方便的扩展方法:
public static string If( this string s,bool condition ) { return condition ? s : String.Empty; }
根据您使用的API,您可能还需要扩展MvcHtmlString.
然后在视图中:
@section Contextual { <div>@Html.ActionLink("Create New","Create").If(Model.CanCrete)</div> <div>@Html.ActionLink("Generate Report","Other")</div> }
你可以决定你想做什么关于div,你可能想要另一个帮助包裹div中的链接,或者你可以使用CSS来实现你想要的任何视觉布局.