受保护的变量和模型绑定
Protected Variables and model binding
请查看以下型号:
public class Apple //: Fruit
{
public string Description { get; set; }
public int Id { get; protected set; }
}
public class AppleModel
{
public int Id { get; set; }
public string Description { get; set; }
}
和下面的控制器:
[HttpPost]
public ActionResult Index(Apple apple)
{
return View();
}
[HttpGet]
public ActionResult Index()
{
var AppleModel = new AppleModel();
AppleModel.Id = 1;
AppleModel.Description = "Apple";
var Apple = AutoMapper.Mapper.Map<Apple>(AppleModel);
return View("View1",Apple);
}
和下面的视图:
@model PreQualification.Web.Controllers.Apple
@{
ViewBag.Title = "View1";
}
<h2>View1</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>AppleModel</h4>
<hr />
@Html.ValidationSummary(true)
<div class="form-group">
@Html.LabelFor(model => model.Id)
<div class="col-md-10">
@Html.EditorFor(model => model.Id)
@Html.ValidationMessageFor(model => model.Id)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Description, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Description)
@Html.ValidationMessageFor(model => model.Description)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Apple.Id 在 HttpPost 方法中为 0,因为它是模型中的受保护变量。反正有这个吗?
我问的原因是因为我试图将其用作模型:https://github.com/nhibernate/NHibernate.AspNet.Identity/tree/master/source/NHibernate.AspNet.Identity 并且超类中包含的 id 受到保护。
有几种解决方法,包括实现 public 的子 class,其 setter 将值应用于受保护的 id 字段。
不过这些都是创可贴。通常遇到这些问题是因为人们对模型的看法不同。它要么是可重复使用的数据传输对象,要么不是。
在不是这样的情况下,您必须将业务对象硬塞进可绑定的模型中,并且总是 运行 陷入这些奇怪的问题中。
在它们所在的世界中,它们是为满足数据需求而定制的,并使用类似自动映射器的东西映射到业务对象中。更重要的是,通过制作模型来满足此要求,您可以防止对意外暴露参数的攻击。
如果临时业务对象具有 public 改变您行为的属性,则可以通过使用 post 请求发回额外参数来利用它们。
我知道这并没有具体回答你的问题,但遵循模型不是 DTO 的路径可能也不是正确的答案。
正如 peewee_RotA 所阐述的那样,最好将用于视图的模型与将实际执行操作或用于直接执行操作的域模型之间的概念差异分开。为此,您需要一个视图模型,例如 Apple
public class Apple
{
public string Description { get; set; }
public int Id { get; set; }
}
在您的 post 操作中,您将拥有;
[HttpPost]
public ActionResult Index(Apple apple)
{
// translate your view model to your domain model
AppleModel model = new AppleModel(apple.Id, apple.Description);
model.DoStuff();
}
尽管就 NHiberhate 而言,使用视图模型的 ID 实例化所需对象并不容易,我认为这是问题的症结所在。您正在尝试将域模型用作视图模型,并且域模型被锁定……合法地。它的工作是控制 IdentityUser
等的实例化方式,因为它们是由关联工厂 类 而不是 MVC 的模型绑定器生成的。
为此,让您的视图模型尽可能简单,并利用 NHibernate 的工厂 类 通过查找 ID 创建必要的 Identity
对象。 This link 可能会阐明如何查找由 Apple.Id
传入的用户 ID。
编辑
我对在 NHibernate 中查找实体做了更多的挖掘,following post 似乎做了一些基础工作。这能满足您的需求吗?
请查看以下型号:
public class Apple //: Fruit
{
public string Description { get; set; }
public int Id { get; protected set; }
}
public class AppleModel
{
public int Id { get; set; }
public string Description { get; set; }
}
和下面的控制器:
[HttpPost]
public ActionResult Index(Apple apple)
{
return View();
}
[HttpGet]
public ActionResult Index()
{
var AppleModel = new AppleModel();
AppleModel.Id = 1;
AppleModel.Description = "Apple";
var Apple = AutoMapper.Mapper.Map<Apple>(AppleModel);
return View("View1",Apple);
}
和下面的视图:
@model PreQualification.Web.Controllers.Apple
@{
ViewBag.Title = "View1";
}
<h2>View1</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>AppleModel</h4>
<hr />
@Html.ValidationSummary(true)
<div class="form-group">
@Html.LabelFor(model => model.Id)
<div class="col-md-10">
@Html.EditorFor(model => model.Id)
@Html.ValidationMessageFor(model => model.Id)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Description, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Description)
@Html.ValidationMessageFor(model => model.Description)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Apple.Id 在 HttpPost 方法中为 0,因为它是模型中的受保护变量。反正有这个吗?
我问的原因是因为我试图将其用作模型:https://github.com/nhibernate/NHibernate.AspNet.Identity/tree/master/source/NHibernate.AspNet.Identity 并且超类中包含的 id 受到保护。
有几种解决方法,包括实现 public 的子 class,其 setter 将值应用于受保护的 id 字段。
不过这些都是创可贴。通常遇到这些问题是因为人们对模型的看法不同。它要么是可重复使用的数据传输对象,要么不是。
在不是这样的情况下,您必须将业务对象硬塞进可绑定的模型中,并且总是 运行 陷入这些奇怪的问题中。
在它们所在的世界中,它们是为满足数据需求而定制的,并使用类似自动映射器的东西映射到业务对象中。更重要的是,通过制作模型来满足此要求,您可以防止对意外暴露参数的攻击。
如果临时业务对象具有 public 改变您行为的属性,则可以通过使用 post 请求发回额外参数来利用它们。
我知道这并没有具体回答你的问题,但遵循模型不是 DTO 的路径可能也不是正确的答案。
正如 peewee_RotA 所阐述的那样,最好将用于视图的模型与将实际执行操作或用于直接执行操作的域模型之间的概念差异分开。为此,您需要一个视图模型,例如 Apple
public class Apple
{
public string Description { get; set; }
public int Id { get; set; }
}
在您的 post 操作中,您将拥有;
[HttpPost]
public ActionResult Index(Apple apple)
{
// translate your view model to your domain model
AppleModel model = new AppleModel(apple.Id, apple.Description);
model.DoStuff();
}
尽管就 NHiberhate 而言,使用视图模型的 ID 实例化所需对象并不容易,我认为这是问题的症结所在。您正在尝试将域模型用作视图模型,并且域模型被锁定……合法地。它的工作是控制 IdentityUser
等的实例化方式,因为它们是由关联工厂 类 而不是 MVC 的模型绑定器生成的。
为此,让您的视图模型尽可能简单,并利用 NHibernate 的工厂 类 通过查找 ID 创建必要的 Identity
对象。 This link 可能会阐明如何查找由 Apple.Id
传入的用户 ID。
编辑
我对在 NHibernate 中查找实体做了更多的挖掘,following post 似乎做了一些基础工作。这能满足您的需求吗?