将代码重新出现在MVC中的每个页面上的正确位置是什么

时间:2015-03-26 11:15:53

标签: c# asp.net asp.net-mvc asp.net-mvc-4 razor

在我的mvc解决方案中,我最初使用viewModel来保存IEnumerable的SelectListItems。这些将用于填充下面的元素的下拉列表

 @Html.DropDownListFor(model => model.Type, Model.PrimaryTypeList, new { data_acc_type = "account", data_old = Model.Type, @class = "js-primary-account-type" })

问题在于,无论何时我必须返回此视图,列表都需要重新填充一些非常重要的内容,如下所示:

if(!ModelState.IsValid){
 using (var typeRepo = new AccountTypeRepository())
            {

                var primTypes = typeRepo.GetAccountTypes();
                var primtype = primTypes.SingleOrDefault(type => type.Text == model.Type);
                model.PrimaryTypeList =
                    primTypes
                    .Select(type => new SelectListItem()
                    {
                        Value = type.Text,
                        Text = type.Text
                    }).ToList();

                }
  return View(model);
}

每次回发都必须重写 - 甚至重新调用(如果放入方法)相同的代码,这对我来说似乎很愚蠢。 - 这同样适用于ViewBag,因为我有大约6个控制器,由于继承和我的页面布局而调用同一个视图。

目前我选择将电话实际放在剃刀上。但这感觉不对,更像是老派的asp。如下所示

@{
ViewBag.Title = "Edit Account " + Model.Name;

List<SelectListItem> primaryTypes = null;
using (var typeRepo = new AccountTypeRepository())
{
    primaryTypes =
        typeRepo.GetAccountTypes()
        .Select(t => new SelectListItem()
        {
            Value = t.Text,
            Text = t.Text
        }).ToList();
}
 @Html.DropDownListFor(model => model.Type, primaryTypes, new { data_acc_type = "account", data_old = Model.Type, @class = "js-primary-account-type" })

不使用完全奇怪的东西。是否有更好的方法来解决这种情况?

更新:在下面的@Dawood Awan半场接听答案时。我的代码有点好,但仍然在视图中,我仍然100%对其他人的想法或答案持开放态度。

当前代码(剃刀和控制器)

  public static List<SelectListItem> GetPrimaryListItems(List<AccountType> types)
    {
        return types.Select(t => new SelectListItem() { Text = t.Text, Value = t.Text }).ToList();
    }
    public static List<SelectListItem> GetSecondaryListItems(AccountType type)
    {
        return type == null?new List<SelectListItem>(): type.AccountSubTypes.Select(t => new SelectListItem() { Text = t.Text, Value = t.Text }).ToList();
    } 

@{
    ViewBag.Title = "Add New Account";
    List<SelectListItem> secondaryTypes = null;
    List<SelectListItem> primaryTypes = null;
    using (var typeRepo = new AccountTypeRepository())
    {
        var primTypes = typeRepo.GetAccountTypes();
        primaryTypes = AccountController.GetPrimaryListItems(primTypes);
        secondaryTypes = AccountController.GetSecondaryListItems(primTypes.SingleOrDefault(t => t.Text == Model.Type));
    }

}

2 个答案:

答案 0 :(得分:1)

在实践中,您需要分析应用程序运行缓慢的位置并首先加快这些部分的速度。

对于初学者,从视图中取出任何类似的代码并将其放回控制器中。使用ViewModel的开销可以忽略不计(速度方面)。最好在控制器中获取所有决策/数据获取代码而不污染视图(视图应该只知道如何呈现特定的数据形状,而不是它来自何处)。

你的&#34;东西非常沉重&#34;评论是非常随意的。例如,如果该查询是在Azure托管网站上的1Gb连接上运行的,那么您将不会注意到或关心那么多。数据库缓存也会起到推动作用。

话虽如此,这确实只是一个缓存问题,并决定在哪里来缓存它。如果数据对所有用户都是通用的,则静态属性(例如在控制器中或全局存储)将提供该静态列表的快速内存重用。

如果数据经常更改,则需要提供刷新内存缓存的功能。

如果您使用IOC /注入,则可以指定在所有请求中共享的单个静态实例。

不要使用每会话数据来存储静态信息。这将减慢系统速度并使用大量用户使你失去内存(即它不能很好地扩展)。

答案 1 :(得分:0)

如果DropDown Values没有改变,最好保存在Session [&#34;&#34;]中,然后你可以访问View,controller等。

在Helpers文件夹中创建一个类:

public class CommonDropDown
{

    public string key = "DropDown";


    public List<SelectListItem> myDropDownItems
    {
        get { return HttpContext.Current.Session[key] == null ? GetDropDown() : (List<SelectListItem>)HttpContext.Current.Session[key]; }
        set { HttpContext.Current.Session[key] = value; }
    }

    public List<SelectListItem> GetDropDown()
    {

        // Implement Dropdown Logic here
        // And set like this:
       this.myDropDownItems = DropdownValues;
    }
}

在共享文件夹中创建部分视图(&#34; _dropDown.cshtml&#34;): 有这样的事情:

@{
    // Add Reference to this Folder
    var items = Helpers.CommonDropDown.myDropDownItems;
}


@Html.DropDownList("ITems", items, "Select")

然后在每页的顶部:

@Html.Partial("_dropDown.cshtml")