我有以下型号: -
[MetadataType(typeof(TMSServer_Validation))]
[Bind(Exclude = "TMSRack,ServerModel")]
public partial class TMSServer
{
}
我的观点中有以下内容: -
@Html.DropDownListFor(model =>model.Server.TMSRack.DataCenterID, ((IEnumerable<TMS.Models.DataCenter>)ViewBag.DataCenters).Select(option => new SelectListItem {
Text = (option == null ? "None" : option.Name),
Value = option.ID.ToString(),
Selected = (Model.Server.TMSRack != null) && (option.ID == Model.Server.TMSRack.DataCenterID)
}), "Choose...")
然后在我的控制器类上,我有以下内容: -
ViewBag.Racks = repository.getrelatedracks(Server.TMSRack.DataCenterID);
但由于我排除了TMSRack
导航属性(主要是为了避免过度发布攻击),因此Server.TMSRack.DataCenterID
始终为null
。为了获得它的价值,我写了以下内容: -
ViewBag.Racks = repository.getrelatedracks(Int32.Parse( Request.Form["Server.TMSRack.DataCenterID"]));
但是我知道使用Request.Form
不是正确的方法,所以我的问题是有一种方法可以使用更可靠的方法来获取被排除的属性吗?
感谢
答案 0 :(得分:2)
我的回答是假设TMSServer
是域模型。
考虑到这一点,这是何时使用视图模型的完美示例。通过使用视图模型,您可以完全控制属性从视图模型到域模型的映射方式。类似的东西:
public class RackViewModel
{
public int DataCenterID
// other Rack properties
}
然后向您的视图发送RackViewModel
列表,或创建包含所有这些内容的视图模型:
public class ContainerViewModel
{
public List<RackViewModel> Racks { get; set; }
// other view-specific properties
}
现在,当您回发数据时,您不仅可以完全控制要绑定到视图模型的属性,还可以完全控制将视图模型转换为域模型时所发生的映射
底线是:如果您的视图接受仅允许用户POST数据的视图模型,则应允许他们进行POST,甚至不存在过度发布。精心设计的视图模型,甚至区分视图模型和输入模型(即表示要在操作中绑定回的数据的单独模型),完全消除了过度发布。
仅存在过度发布,因为您没有足够地限制模型绑定过程。如果你要求它绑定到一个包含10个属性的类,当你只需要3时,你就允许用户将数据填充到其他7个属性中。
这是视图模型如此受欢迎的一个原因。它们允许您缩小视图范围,同时缩小模型绑定器的范围。这使您可以自由地正确管理从视图模型到域模型的映射过程,而不会引入漏洞。
由于您不想采用视图模型方法,您的想法会起作用,但您可以稍微改变一下。有点像:
public ActionResult SomeAction(SomeModel model, TMSRack rack)
其中:
SomeModel
是您使用Bind(Exclude...)
进行装饰的模型类型(不清楚您问题的类型。TMSRack
是我想要绑定的类型。无论如何,在你的主模型中定义TMSRack
,只要你使用Html.*
助手,它就会在表单上为它生成正确的名称,以便直接绑定将它作为您行动的单独参数。然后你可以随心所欲地做任何事情,而无需诉诸Request.Form
。