1

我正在使用 MS Sql server 2008 express rc2 开发 asp.net mvc3 Web 应用程序。在我的应用程序中,我在 DB 中有两个不同的品牌,其中一个几乎没有 Null 或“未知”值(例如,将“未知”添加到 DB 而不是 Null)。我的问题是如何仅将非空值传递给 View Engine,而不是在 View 中使用 If/Else 语句?

在控制器中:

var model = _data.GetViewModel(query);
        if (model != null)
        {                
            return View(model);
        }
        else
            return View("Error");

在视图模型中;

    public int Id { get; set; }
    public string Query { get; set; }
    public string Brand { get; set; }
    public string Family { get; set; }
    public string Type { get; set; }

在模型中:

    public ViewModel GetViewModel(string query)
    {
        var data = _comp.Get(p => p.Query == query);
        if (data == null) return null;
        return new ViewModel
        {
            Id = data.id,
            Brand = data.brand,
            Family = data.family,
            Type = data.type
        };
   }

在视图中(我目前正在使用 If 语句):

@if (Model.Brand != null)
{
<span class="brand">@Model.Brand</span> 
}

@if (Model.Family != null)
{
<span class="family">@Model.Family</span> 
}

@if (Model.Type != null)
{
<span class="type">@Model.Type</span>
}

注意:我想避免If语句,因为每个品牌的Database中的值太多,而且其中很多是Null,所以我不想为那些Null值生成Html。我正在使用像上面的代码一样的 If/Else 语句,并且为了使用 If 检查 View 中的太多值,它会消耗服务器和处理器上的内存,并且还会减慢服务器响应时间。

我想有另一种方法来做到这一点。我应该使用局部视图还是其他任何东西?请帮我解决这个问题,非常感谢您的帮助。谢谢并恭祝安康。

4

2 回答 2

3

首先,一些背景/背景,然后是我的建议。

(顺便说一句,这一切都适用于任何版本的 ASP.NET MVC 或 ASP.NET NancyFX(是的,还有另一个选项!!)等)

背景/背景

为了解决这个问题,人们通常分为两类:

  1. 只需获取数据并让视图决定显示什么(常见的,而不是 IMO 的正确方式)。
  2. Controller应该处理所有繁重的工作并为视图提供确切答案(正确的方式,IMO)。

第一种方法既快又脏。当然它有效,但它在视图中加入了太多逻辑。Views根本不应该做任何逻辑(例外:for循环,也许是奇怪的if/else,也许)。主要原因是测试。是的,人们讨厌并认为它只适用于嬉皮士的那个肮脏的词。或者..我没有时间测试..所以我手动测试等等。如果您将任何业务逻辑放入视图中,您将无法对其进行测试。

第二种方法一开始可能看起来有点慢,但这就像任何事情一样——你练习得越多,你走得越快。这是(IMO)首选的做事方法,因为您可以测试控制器。控制器应该创建一个视图模型,该模型将具有视图所需的确切结果。不是多余的。例如,假设您想将列表返回Brands到显示/视图。大多数人会(相当于)将所有品牌放入列表中,并将该列表发送到视图,即使 80% 的属性不会被该视图使用!即使该视图不会使用 ONE 属性,也不要检索它或将其发送到视图!

所以-TL;DR;在控制器中完成所有繁重的工作。观点是愚蠢的。只需将确切的视图模型数据转储到视图中。

解决您的问题

好的,让我们继续使用想法 #2,让所有这些事情都发生在控制器中。

// Grab the results.
// ASSUMPTION: It is only returning the -exact- data I need. No more, no less.
var results = _data.GetViewModel(query);
if (model == null)
{                

// Project the results into a perfectly tight & svelte view model 
// 100% specific for this view.
var viewModel = results.
                Select(x => new ViewModel
                {
                    Id = x.Id,
                    Brand = string.IsNullOrEmpty(x.Brand) 
                              ? string.Empty 
                              : x.Brand,
                    Family = string.IsNullOrEmpty(x.Family) 
                              ? string.Empty 
                              : x.Family,
                    Type = string.IsNullOrEmpty(x.Type) 
                              ? string.Empty 
                              : x.Type,
                }).ToList();    


return viewModel;

测试这个..

[Fact]
public void GivenSomeBrands_Index_ReturnsAViewModel()
{
    // Arrange.
    // NOTE: Our fake repostitory has some fake data. In it ..
    //       Id: 1, Brand: Gucci.
    //       Id: 22, Brand: null.
    var controller = new BrandController(SomeFakeRepositoryThingy);

    // Act.
    var result = controller.Index(); // This calls that controller code, above.

    // Assert.
    Assert.IsNotNull(result); // Controller returned some result.
    Assert.IsNotNull(result.Model); // We have some model data.

    var model = result.Model as IList<ViewModel>(); // Cast the Model value.
    Assert.NotNull(model); // We have a strongly typed view model.

    // We check the first brand value.
    Assert.Equal("Gucci", model.First().Brand); 

    // We know this item has a null Brand, 
    Assert.Equal(string.Empty, model[21].Brand); but the ViewModel converted it.
}
于 2013-08-15T00:27:58.810 回答
0

您可以编写一个自定义 HTML 助手:

public static string MyHelper<V>(this HtmlHelper helper, V value, string css)
{
    if (value == null)
        return "";

    return String.Format("<span class='{0}'>{1}</span>", value, css);
}

那么在你看来:

@Html.MyHelper(Model.Brand, "brand");
@Html.MyHelper(Model.Family, "family");
@Html.MyHelper(Model.Type, "type");
于 2013-08-14T23:57:01.300 回答