简体   繁体   English

带有null selectList参数的Html.DropDownListFor

[英]Html.DropDownListFor with null selectList parameter

This is taken from VS Add New Scaffolded Item... when creating a new controller. 这是在创建新控制器时从VS Add New Scaffolded Item...

In the controller: 在控制器中:

// GET: Drivers/Create
public ActionResult Create()
{
    ViewBag.Tenant = new SelectList(db.Tenants, "TenantID", "TenantName");
    return View();
}

The view then renders a drop-down list: 然后该视图呈现一个下拉列表:

@Html.DropDownListFor(model => model.Tenant, null, htmlAttributes: new { @class = "form-control" })

The relevant model information: 相关型号信息:

public partial class Driver
{
    public int DriverID { get; set; }
    public int Tenant { get; set; }
    public virtual Tenant Tenant1 { get; set; }
}

public partial class Tenant
{
    public Tenant()
    {
        this.Drivers = new HashSet<Driver>();
    }

    public int TenantID { get; set; }
    public string TenantName { get; set; }
    public virtual ICollection<Driver> Drivers { get; set; }
}

Can someone explain why this works? 有人可以解释为什么这有效吗?

I looked at other questions and documentation and couldn't find the answer. 我查看了其他问题和文档,找不到答案。 I suspect it is something along the lines of "convention over configuration" and it is pulling from the ViewBag using the name of the property. 我怀疑它是“约定优于配置”的东西,它是使用属性的名称从ViewBag提取的。 In fact, I changed the ViewBag property to Tenantz and got the following exception: 事实上,我将ViewBag属性更改为Tenantz并获得以下异常:

There is no ViewData item of type 'IEnumerable' that has the key 'Tenant'. 没有类型为“IEnumerable”的ViewData项具有“租户”键。

So is setting the property name of the ViewBag the same as the model property you want to update a good practice? 那么设置ViewBag的属性名称与您想要更新良好实践的模型属性相同吗? It seems ok but I always hear how you should avoid ViewBag and dynamic types. 看起来没问题,但我总是听说你应该如何避免使用ViewBag和动态类型。

As you have already discovered there's a convention. 正如您已经发现的那样,有一个惯例。 The following line in your view: 您视图中的以下行:

@Html.DropDownListFor(model => model.Tenant, null, htmlAttributes: new { @class = "form-control" })

is exactly the same as this line: 与此行完全相同:

@Html.DropDownList("Tenant", null, htmlAttributes: new { @class = "form-control" })

Now if you look at how the DropDownList helper is implemented in the source code you will notice that it simply does that: 现在,如果您看一下如何在源代码中实现DropDownList帮助器,您会注意到它只是这样做:

object obj = htmlHelper.ViewData.Eval(name) as IEnumerable<SelectListItem>;

where name is the first argument passed to the DropDownList helper. 其中name是传递给DropDownList帮助器的第一个参数。 And guess what? 你猜怎么着? It discovers the corresponding value that you have set in your controller: ViewBag.Tenant = ... . 它会发现您在控制器中设置的相应值: ViewBag.Tenant = ...

This being said using ViewBag is an absolutely, disastrously, terribly bad practice. 据说使用ViewBag是绝对的,灾难性的,非常糟糕的做法。 You've already find out why. 你已经找到了原因。 It can bite you like a dog without you even knowing what's going on. 它可以像狗一样咬你,甚至不知道发生了什么。 The best way to protect against those dogs ( ViewBag ) is to search them inside your solution and give them poison. 防止这些狗( ViewBag )的最佳方法是在你的解决方案中搜索它们并给它们毒药。 Simply get rid of absolutely any ViewBag calls in your code and use view models. 只需在代码中删除绝对任何ViewBag调用并使用视图模型。 Then you will not get bad surprises and everything will have a reasonable explanation and questions like this wouldn't be necessary on StackOverflow. 然后你不会得到不好的惊喜,一切都会有一个合理的解释,在StackOverflow上没有必要这样的问题。

Like for example you could write a normal view model: 例如,您可以编写普通视图模型:

public class DriverViewModel
{
    public int? SelectedTenantID { get; set; }

    public IEnumerable<SelectListItem> Tenants { get; set; }
}

and a normal controller action that will query your datastore for the required information and project your entity model to the view model: 和一个正常的控制器操作,它将查询您的数据存储区以获取所需信息并将您的实体模型投影到视图模型:

// GET: Drivers/Create
public ActionResult Create()
{
    var viewModel = new DriverViewModel();
    viewModel.Tenants = new SelectList(db.Tenants, "TenantID", "TenantName");
    return View(viewModel);
}

and finally the corresponding strongly typed view: 最后是相应的强类型视图:

@model DriverViewModel
...
@Html.DropDownListFor(
    model => model.SelectedTenantID, 
    Model.Tenants, 
    htmlAttributes: new { @class = "form-control" }
)

In this case you are using a strongly typed view, with a strongly typed view model and a helper. 在这种情况下,您使用强类型视图,具有强类型视图模型和帮助程序。 There are no longer any doubts (and dogs that bite). 不再有任何疑虑(和狗咬)。 The code is readable and you cannot ask, why this convention over configuration is doing this or that. 代码是可读的,你不能问,为什么这个约定超过配置正在做这个或那个。 So as long as there's no trace of ViewBag in your application there will be no such questions. 因此,只要您的应用程序中没有ViewBag的痕迹,就不会有这样的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM