【发布时间】:2012-03-20 04:51:56
【问题描述】:
通过以下简单的操作...
[HttpPost]
public PartialViewResult DoSomething(AnimalInfo animalInfo)
{
// animalInfo.AnimalKey SHOULD == DogKey { Id = 1, Name = "Dog" }
// BUT animalInfo.AnimalKey == null
return Something();
}
发布到此操作很好,并且animalInfo 的大多数属性都可用,除了我自己创建的对象。我假设这是一个序列化问题,所以我在我的类中添加了一些基本的序列化,但 AnimalKey 对象仍然为 null(在渲染时绝对不是 null)。
我是这样定义 AnimalInfo 的:
[DataContract]
public class AnimalInfo : IAnimalInfo
{
[DataMember]
public IAnimalKey AnimalKey { get; set; }
public string Name { get; set; }
}
[DataContract]
public class DogKey : IAnimalKey
{
public DogKey(int id){ DogId = id; }
[DataMember]
public int DogId { get; set; }
}
我从这样的视图发布到 Action...
<% var currentAnimal = new AnimalInfo { AnimalKey = new DogKey(1), Name = "Dog" }; %>
<% using (Html.BeginForm("DoSomething", "Controller", currentAnimal.AnimalInfo))
{
%><button type="submit">post</button><%
} %>
但是当我的动作被执行时,AnimalKey 已经变为空,而 Name 是“Dog”。调查 ModelState 也发现了同样的情况。这似乎是一个序列化问题。是这样吗?如果是这样,DataContract 和 DataMember 是否不足以作为处理此问题的方法?
更新
作为一种替代方法,我尝试将其更改为强类型视图并使用 HiddenFor 发布数据,但我仍然得到完全相同的结果。
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Namespace.IAnimalInfo>" %>
<% using (Html.BeginForm("DoSomething", "OM", Model))
{
Html.HiddenFor(m => m.AnimalKey);
Html.HiddenFor(m => m.Name);
%><button type="submit">revert</button><%
} %>
MVC HtmlHelpers 根本不序列化复杂对象吗?
或者我是否需要为每个 AnimalKey 创建不同的模型才能取回这些值?
或者甚至将我自己的序列化写入一个隐藏的字符串,然后在返回时反序列化它?
可能的原因
经过一番折腾,我很确定这是因为 IAnimalKey 是一个接口。当我向模型添加另一个名为 DogKey 的属性时,将返回该值。因此,它似乎失去了关于帖子上的对象类型或根本不支持接口的知识。
脏修复
看我的回答
【问题讨论】:
-
我不认为你可以像这样将丰富的对象传递给
BeginForm。该对象用于创建RouteValueCollection,它只是一个平面字典,而不是完整的对象树。 -
如果你看一下 Html.HiddenFor(m => m.AnimalKey); 生成的 HTML,它是什么样子的——生成的隐藏字段的名称是什么,它的值是什么?
-
我只是面临着类似的情况......无论我尝试什么
ConcurrencyCheck类型的byte[]属性都不会添加到ModelState。你猜怎么了?它在接口中声明,然后在每个POCO对象上声明。我必须创建ViewModels。没有其他方法可以开箱即用。我认为ViewModel是要走的路。更多代码在路上... :D 不管怎样,你做了一些艰苦的代码!恭喜...
标签: .net asp.net-mvc serialization model-binding modelstate