MVC 3.0中的默认模型绑定器是否能够处理非顺序索引(对于简单和复杂模型类型)?我遇到的帖子表明应该这样做,但是在我的测试中它似乎没有.
给出后期值:
items[0].Id = 10
items[0].Name = "Some Item"
items[1].Id = 3
items[1].Name = "Some Item"
items[4].Id = 6
items[4].Name = "Some Item"
Run Code Online (Sandbox Code Playgroud)
和控制器方法:
public ActionResult(IList<MyItem> items) { ... }
Run Code Online (Sandbox Code Playgroud)
加载的唯一值是项0和1; 第4项被忽略了.
我已经看到了许多生成自定义索引的解决方案(模型绑定到列表),但是它们似乎都是针对MVC的早期版本,而且大多数都是有点"严厉"的IMO.
我错过了什么吗?
我有一个类型:
public class IssueForm
{
Order Order {get; set;}
Item Item {get; set;}
Range Range {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
由于Order和Item的要求,我创建了一个自定义模型绑定器,但Range仍然可以使用Default Model Binder.
我的自定义模型绑定器中是否有一种方法可以调用默认模型绑定器来返回Range对象?我想我只需要正确设置ModelBindingContext,但我不知道如何.
编辑
查看第一个评论和答案 - 似乎从默认模型绑定器继承可能很有用.
到目前为止为我的设置添加更多细节我有:
public IssueFormModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
Order = //code to pull the OrderNumber from the context and create an Order
Item = //code to pull the ItemNumber from the context and create an Item
IssueForm form = IssueFormFactory.Create(Order, Item);
form.Range = // ** I'd like to replace …
Run Code Online (Sandbox Code Playgroud) 我知道将域模型用作视图模型可能会很糟糕.如果我的域模型有一个名为IsAdmin的属性并且我有一个Create控制器操作来创建用户,那么即使我没有在我的视图中公开这样的文本字段,也有人可以改变我的表单并使其发布一个IsAdmin = true表单值. .如果我正在使用模型绑定,那么当我提交我的域模型时,该人现在将成为管理员.因此,解决方案只是在视图模型中公开我需要的属性,并使用AutoMapper之类的工具将我返回的视图模型对象的属性值映射到我的域模型对象的属性值.但是我读到类上的bind属性可以用来指示Model Binder它应该和不应该绑定哪些属性.那么究竟是什么原因使得两个独立的类(领域模型和视图模型)必须代表相同的东西,然后在映射它们时增加开销呢?这是一个代码组织问题,如果是这样,我如何受益?
编辑
我遇到的与域模型分离的视图模型的最重要原因之一是需要实现MVVM模式(基于Martin Fowler的PM模式)来管理复杂的UI.
我一直在网上寻找答案或例子,但还找不到一个.我只想更改默认的JSON序列化程序,用于在模型绑定到JSON.NET库时反序列化JSON.
我发现这个 SO帖子,但到目前为止无法实现它,我甚至看不到System.Net.Http.Formatters
命名空间,也看不到GlobalConfiguration
.
我错过了什么?
UPDATE
我有一个ASP.NET MVC项目,它基本上是一个MVC3项目.目前我的目标是.NET 4.5并使用ASP.NET MVC 5和相关的NuGet包.
我没有看到System.Web.Http程序集,也没有看到任何类似的命名空间.在这个上下文中,我想注入JSON.NET作为JSON类型请求的默认模型绑定器.
有没有办法让发布的文件(<input type="file" />
)参与ASP.NET MVC中的模型绑定,而无需在自定义模型绑定器中手动查看请求上下文,而无需创建仅将已发布文件作为输入的单独操作方法?
我原以为这会起作用:
class MyModel {
public HttpPostedFileBase MyFile { get; set; }
public int? OtherProperty { get; set; }
}
<form enctype="multipart/form-data">
<input type="file" name="MyFile" />
<input type="text" name="OtherProperty" />
</form>
public ActionResult Create(MyModel myModel) { ... }
Run Code Online (Sandbox Code Playgroud)
但鉴于上述情况,MyFile
甚至不是绑定上下文中值提供者值的一部分.(OtherProperty
当然是.)但如果我这样做,它会起作用:
public ActionResult Create(HttpPostedFileBase postedFile, ...) { ... }
Run Code Online (Sandbox Code Playgroud)
那么,当参数是模型时,为什么没有绑定发生,我怎样才能使它工作?我使用自定义模型绑定器没有问题,但是如何在不看的情况下在自定义模型绑定器中执行此操作Request.Files["MyFile"]
?
为了保持一致性,清晰度和可测试性,我希望我的代码能够自动绑定模型上的所有属性,包括绑定到已发布文件的属性,而无需手动检查请求上下文.我目前正在使用Scott Hanselman撰写的方法测试模型绑定.
或者我是以错误的方式解决这个问题?你怎么解决这个问题?或者,由于Request.Form和Request.Files之间的分离历史,这是不可能的设计?
asp.net-mvc defaultmodelbinder modelbinders httppostedfilebase
我想为DateTime
类型编写自己的模型绑定器.首先,我想写一个我可以附加到我的模型属性的新属性,如:
[DateTimeFormat("d.M.yyyy")]
public DateTime Birth { get; set,}
Run Code Online (Sandbox Code Playgroud)
这是简单的部分.但是粘合剂部分有点困难.我想为类型添加一个新的模型绑定器DateTime
.我也可以
IModelBinder
接口并编写我自己的BindModel()
方法DefaultModelBinder
和覆盖BindModel()
方法我的模型有如上所示的属性(Birth
).因此,当模型尝试将请求数据绑定到此属性时,BindModel(controllerContext, bindingContext)
将调用我的模型绑定器.一切都好,但是.如何从controller/bindingContext获取属性属性,以正确解析我的日期?我怎样才能到达PropertyDesciptor
房产Birth
?
由于关注点的分离,我的模型类是在一个没有(也不应该)引用System.Web.MVC程序集的程序集中定义的.设置自定义绑定(类似于Scott Hanselman的示例)属性是禁止的.
ASP.NET MVC中的模型绑定很棒,但它遵循区域设置.在我的语言环境中,小数点分隔符是逗号(','),但用户也使用点('.'),因为它们懒得切换布局.我想在一个地方为decimal
我的模型中的所有字段实现这个.
我应该为decimal
类型实现自己的Value Provider(或事件Model Binder),还是我错过了一些简单的方法来做到这一点?
我试图调试为什么MVC在给定的情况下没有正确绑定我有一点点困难我...
基本上,我有我的动作接收一个复杂的对象,而这个对象又有一个复杂的子对象 - Activity.Location.State(其中Activity是动作所期望的复杂对象,Location是一个复杂的子对象,State只是一个字符串) .
现在我建立了一个测试项目,据我所知,我确切地模仿了我的实际场景,在这个测试用例中绑定有效...但在我的实际项目中,绑定到Activity工作但不是位置...通过在Locaiton属性中放置断点,我可以告诉MVC从Activity中检索复杂的Location对象,但它没有设置任何属性......
我正在尝试调试这个问题,但我需要访问MVC v2预览2符号,这些符号似乎无法跟踪...我希望看到它实际上做了什么,一旦它拉出位置对象(对于一些我之所以认为它可能在内部失败但吞下这个例外).
关于我在这里可以做什么的任何想法......
干杯安东尼
更新:
好的我做了JW建议并直接引用MVC项目......
我发现了这个问题,并且我忽略了一个非常小的差异......正如我的结果我发现当涉及到模型绑定时,MVC当前不支持多层INTERFACE继承...请参阅以下内容......
//MODEL
public class Location : ILocation
{
...
}
public interface ILocation : ILocationCore
{
...
}
public interface ILocationCore //In my sample I didn't have this second level interface
{
...
//MVC doesn't find any of these properties
...
}
public class Activity : IActivity
{
...
}
public interface IActivity : IActivityCore
{
ILocation Location { get; set; } //MVC finds this and reads its …
Run Code Online (Sandbox Code Playgroud) 我在项目中编写了自定义模型绑定器,它使用ASP.NET MVC 2.此模型绑定器仅绑定2个模型字段:
public class TaskFormBinder : DefaultModelBinder
{
protected override void BindProperty(ControllerContext controllerContext,
ModelBindingContext bindingContext,
PropertyDescriptor propertyDescriptor)
{
if (propertyDescriptor.Name == "Type")
{
var value = bindingContext.ValueProvider.GetValue("Type");
var typeId = value.ConvertTo(typeof(int));
TaskType foundedType;
using (var nhSession = Domain.GetSession())
{
foundedType = nhSession.Get<TaskType>(typeId);
}
if (foundedType != null)
{
SetProperty(controllerContext, bindingContext, propertyDescriptor, foundedType);
}
else
{
AddModelBindError(bindingContext, propertyDescriptor);
}
return;
}
if (propertyDescriptor.Name == "Priority")
{ /* Other field binding ... */
return;
}
base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
}
}
Run Code Online (Sandbox Code Playgroud)
如何使用标准VS单元测试来测试此模型绑定器?花了几个小时谷歌搜索,找到几个例子( …
编辑:添加了赏金,因为我正在寻找除此之外的MVC3解决方案(如果存在):
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
我的"地址"模型上有一个只读属性'CityStateZip'
.
这是从美国地址获取城市,州,邮政的便捷方式.如果该国家不是美国(调用者应首先检查),则会抛出异常.
public string CityStateZip
{
get
{
if (IsUSA == false)
{
throw new ApplicationException("CityStateZip not valid for international addresses!");
}
return (City + ", " + StateCd + " " + ZipOrPostal).Trim().Trim(new char[] {','});
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的模型的一部分,所以它受到约束.在ASP.NET MVC2 RC2之前,此字段在数据绑定期间从未引起过问题.我从来没有真正想过它 - 毕竟它只是只读.
现在虽然在2010年1月的RC2版本中,它在数据绑定期间给出了一个错误 - 因为默认模型绑定器似乎想要检查此值(即使它是只读的).
它是'base.OnModelUpdated'行导致触发此错误.
public class AddressModelBinder : DefaultModelBinder
{
protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
base.OnModelUpdated(controllerContext, bindingContext);
Run Code Online (Sandbox Code Playgroud)
最后几分钟对模型绑定器的更改显然导致了行为的这种变化 - 但我还不确定它的重现是什么 - 或者这是否是一个错误?我正在将此传递给MVC团队,但好奇是否有人在此期间有任何建议我如何阻止此属性绑定.
这篇文章非常值得一读 - 但是根本没有提到readonly属性(不是我期望的).问题(如果有的话)可能比这种情况更广泛 - 我只是不确定是否有任何反复 - …
modelbinders ×10
asp.net-mvc ×7
asp.net ×2
binding ×1
c# ×1
json.net ×1
model ×1
unit-testing ×1
viewmodel ×1