jga*_*fin 4 asp.net asp.net-mvc refactoring
我对ASP.Net和MVC都很陌生.
我在母版页中获得了以下代码:
<div id="main-menu" class="menu">
<%
var items = (IList<CompanyName.Framework.Web.MenuItem>)ViewData["MainMenu"];
if (items.Count > 0)
{
%><ul><%
foreach (var item in items)
{
if (!string.IsNullOrEmpty(item.RequiredRole) && !System.Threading.Thread.CurrentPrincipal.IsInRole(item.RequiredRole))
continue;
%><li><a href="<%= item.Uri %>"><%= item.Title %></a></li><%
}
%></ul><%
}
%>
</div>
Run Code Online (Sandbox Code Playgroud)
我可以将代码移动到另一个文件或以任何方式重构代码吗?
编辑:
我的ApplicationController,所有控制器派生:
public class ApplicationController : Controller
{
List<MenuItem> _mainMenu = new List<MenuItem>();
List<MenuItem> _contextMenu = new List<MenuItem>();
protected IList<MenuItem> MainMenu
{
get { return _mainMenu; }
}
protected IList<MenuItem> ContextMenu
{
get { return _contextMenu; }
}
protected string PageTitle { get; set; }
protected override void OnResultExecuting(ResultExecutingContext filterContext)
{
ViewData["PageTitle"] = PageTitle;
ViewData["MainMenu"] = MainMenu;
ViewData["ContextMenu"] = ContextMenu;
base.OnResultExecuting(filterContext);
}
}
Run Code Online (Sandbox Code Playgroud)
Here are a couple of suggestions:
Improvement number 1: use view models and strongly typed views instead of ViewData
public ActionResult Index()
{
// TODO: Fetch this data from a repository
var menus = new[] {
new MenuItem(), new MenuItem()
}.ToList();
return View(menus);
}
Run Code Online (Sandbox Code Playgroud)
and then in your view:
<div id="main-menu" class="menu">
<%
if (Model.Count > 0)
{
%><ul><%
foreach (var item in Model)
{
if (!string.IsNullOrEmpty(item.RequiredRole) && !System.Threading.Thread.CurrentPrincipal.IsInRole(item.RequiredRole))
continue;
%><li><a href="<%= item.Uri %>"><%= item.Title %></a></li><%
}
%></ul><%
}
%>
</div>
Run Code Online (Sandbox Code Playgroud)
Still horrible and completely unreadable tag soup.
Improvement number 2: use editor/display templates:
In ~/Views/Home/DisplayTemplates/MenuItem.ascx:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<CompanyName.Framework.Web.MenuItem>" %>
<% if (!string.IsNullOrEmpty(Model.RequiredRole) &&
System.Threading.Thread.CurrentPrincipal.IsInRole(Model.RequiredRole)) { %>
<li>
<a href="<%= Model.Uri %>"><%= Model.Title %></a>
</li>
<% } %>
Run Code Online (Sandbox Code Playgroud)
And then in your main view:
<div id="main-menu" class="menu">
<ul>
<%= Html.DisplayForModel() %>
</ul>
</div>
Run Code Online (Sandbox Code Playgroud)
改进3:避免在视图中编写业务规则.所以在你的视图模型中添加一个属性:
public bool IsLinkVisible
{
get
{
return !string.IsNullOrEmpty(RequiredRole) &&
Thread.CurrentPrincipal.IsInRole(RequiredRole);
}
}
Run Code Online (Sandbox Code Playgroud)
这样你的显示模板现在看起来像这样:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<CompanyName.Framework.Web.MenuItem>" %>
<% if (Model.IsLinkVisible) { %>
<li>
<a href="<%= Model.Uri %>"><%= Model.Title %></a>
</li>
<% } %>
Run Code Online (Sandbox Code Playgroud)
改进4:编写自定义HTML帮助器来渲染此锚点,因为在视图中编写C#仍然是丑陋且不可测试的:
public static class HtmlExtensions
{
public static MvcHtmlString MenuItem(this HtmlHelper<MenuItem> htmlHelper)
{
var menuItem = htmlHelper.ViewData.Model;
if (!menuItem.IsLinkVisible)
{
return MvcHtmlString.Empty;
}
var li = new TagBuilder("li");
var a = new TagBuilder("a");
a.MergeAttribute("href", menuItem.Uri);
a.SetInnerText(menuItem.Title);
li.InnerHtml = a.ToString();
return MvcHtmlString.Create(li.ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
最后你的显示模板:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<CompanyName.Framework.Web.MenuItem>" %>
<%= Html.MenuItem() %>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1055 次 |
| 最近记录: |