ASP.NET MVC:特定于页面的逻辑

时间:2009-06-01 07:49:15

标签: asp.net-mvc architecture code-behind

关于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() ...
}

3 个答案:

答案 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>