关于ASP.NET MVC and Codebehind-files的讨论很多,主要是指出这些Codebehind-files are evil。
所以我的问题是,你如何处理特定于页面的逻辑??
我们不希望这里的是内联代码中的意大利面条代码,而我们不希望特定于页面的代码分散在整个帮助程序类中HTML-helper-class的顶部。
一个例子是:
<% for(int i = 0; i < companyList.Count; i++) { %>
RenderCompanyNameWithRightCapsIfNotEmpty(company, i)
<% } %>
随附代码隐藏:
private string RenderCompanyNameWithRightCapsIfNotEmpty(string company, index)
{
if (index == 0) {
return string.Format("<div class=\"first\">{0}</div>", company);
}
// Add more conditional code here
// - page specific HTML, like render a certain icon
string divClass = (index % 2 == 0) ? "normal" : "alternate";
return string.Format("<div class=\"{1}\">{0}</div>", company, divClass);
}
这只会在一个页面上使用,很可能会发生变化。
更新:我想到了几个方法:
1)页面上的内联代码隐藏 - 使用返回字符串的简单方法。
<script runat="server">
private string RenderCompanyHtml(string companyName) ...
<script>
2)在Controller中放置一个返回字符串的方法。但那将将View-logic放入Controller 。
public class SomeController : Controller
{
[NonAction]
private static string RenderCompanyHtml(string companyName) ...
public ActionResult Index() ...
}
答案 0 :(得分:3)
您应该将该代码放在准备viewdata的控制中。
我通常在我的控制器类中使用一些[NonAction]方法创建一个区域“辅助方法”以保持清洁。
所以我的(简化)控制器看起来像这样:
public class SomeController : Controller
{
#region Helper methods
[NonAction]
private static string CompanyNameWithRightCapsIfNotEmpty(string company)
{
if (string.IsNullOrEmpty(company)) {
return company;
}
return UpperCaseSpecificWords(company);
}
#endregion
public ActionResult Companies()
{
var companies = GetCompanies();
var companyNames = companies.Select(c => CompanyNameWithRightCapsIfNotEmpty(c.Name));
ViewData["companyNames"] = companyNames;
return view();
}
}
答案 1 :(得分:2)
帮助程序方法是处理特定于页面的代码的一种好方法,但我认为它是一种方法;让模型显示所需数据的方法更为可取。
如果您打算使用帮助程序选项,那么通过使其运行更少页面特定,您可以获得更好的服务。如果您的方法RenderCompanyNameWithRightCapsIfNotEmpty必须如此具体,那么如果您的模型提供它会更好。一种方法是让模型提供一个包含已经格式化的文本的列表,并将其公开为公共属性(比如IEnumerable格式化的公司名称)。
答案 2 :(得分:1)
使用Html助手。
像这样在static
类中创建辅助方法:
public static string Label(this HtmlHelper helper, string target, string text)
{
return String.Format("<label for='{0}'>{1}</label>", target, text);
}
..然后在你的视图中使用:
<span><% =Html.Label("FinishDateTime.LocalDatetime", "Finish Time:")%><br />
您可以创建一个名为maybe RenderCompanyName(string[] companies)
的辅助方法来检查空值,进行大写操作并在其间渲染html - 如果您愿意,可以在同一个帮助程序中。
另外:控制器动作方法应该很轻 - 即。只获取数据并返回视图。您应该将诸如操作数据之类的内容委托给视图和Html帮助程序。
编辑:以下是您可能会遇到的帮助:
此帮助程序以无序列表IList<>
的形式呈现<ul>...</ul>
到html。有用的是它可以让你控制列表的呈现方式通过css AND 它可以让你为每个项目渲染额外的html /内容。看看 - 这是帮手:
public static string UnorderedList<TItem>(this HtmlHelper helper,
IList<TItem> items, Func<TItem, string> renderItemHtml,
string ulID, string ulClass, string liClass)
{
StringBuilder sb = new StringBuilder();
// header
if (!ulID.IsNullOrTrimEmpty()) sb.AppendFormat("<ul id='{0}'", helper.Encode(ulID.Trim()));
else sb.AppendFormat("<ul");
if (!ulClass.IsNullOrTrimEmpty()) sb.AppendFormat(" class='{0}'>", helper.Encode(ulClass.Trim()));
else sb.AppendFormat(">");
// items
foreach (TItem i in items)
{
if (!liClass.IsNullOrTrimEmpty())
sb.AppendFormat("<li class='{0}'>{1}</li>", helper.Encode(liClass.Trim()),
renderItemHtml(i));
else
sb.AppendFormat("<li>{0}</li>", renderItemHtml(i));
}
// footer
sb.AppendFormat("</ul>");
return sb.ToString();
}
..使用它很容易。这是一个呈现标签列表的简单示例:
<div id="tags">
<h2>Tags</h2>
<%=Html.UnorderedList<Tag>(Model.Tags.Tags,tag=>
{
return tag.Name;
},null,null,null) %>
</div>
..你可以在我的用法示例中看到我选择不指定任何css或id属性,我只是通过使用匿名委托返回Tag
项的名称。匿名代表很容易使用..在你的情况下,也许这样的东西可以工作:
<div id="tags">
<h2>Tags</h2>
<%=Html.UnorderedList<string>(ViewData["companies"],company=>
{
if (someCondition) return company.ToUpper();
else return company;
},null,null,null) %>
</div>
.. ViewData["companies"]
为简单起见IList<string>
。