- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用当前可用的 OData NuGet 包编写带有 Web API 2 的 OData V4 服务。
我有一个类 Foo
的实体集像这样:
class Foo {
string SomePropertyUnrelatedToThePost {get; set;}
...
IList<Bar> TheImportantPropertyList {get; set;}
}
Bar
没有太多的事情发生:
class Bar {
string Name {get; set;}
int? Group {get; set;}
object Value {get; set;}
}
在使用中,除了基本值之外,Bar#Value 从未被分配任何其他值,但有些是原始值,有些不是:bool、byte、char、short、int、long、string、Decimal、DateTime...
我正在按照文档说明注册 Foo 集,使用 ODataConventionModelBuilder,如下所示:
...
builder.EntitySet<Foo>("Foos");
并注册我的 Bar
作为 builder.ComplexType<Bar>();
的复杂类型似乎并没有改变这里的结果。
问题是当我在我的 ODataController 中返回一个 Foo 对象时,JSON 响应不包括 Bar#Value。
{
...
"SomePropertyUnrelatedToThePost": "Foo was here",
...
"TheImportantPropertyList": [
{
"Name": "TheAnswer",
"Group": null
},
{
"Name": "TheQuestion",
"Group": null
}
]
}
让我更加困惑的是,我可以像这样在我的 Controller 方法中手动序列化一个 Foo:
var settings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;//.CreateJsonSerializer();
var s = JsonSerializer.Create(settings);
...
var json = Encoding.Default.GetString(...);
生成正确序列化的结果:
{
"SomePropertyUnrelatedToThePost": "Foo was here",
...
"TheImportantPropertyList": [
{
"Name": "TheAnswer",
"Value": 42,
"Group": null
},
{
"Name": "TheQuestion",
"Value": "What is the airspeed velocity of an unladen swallow?",
"Group": null
}
]
}
我是否错误地配置了 OData?我还有其他一些核心误解吗? 当我写这个问题时,我突然想到,如果我更改我的模型以包含分配的 Value 属性的 System.Type,我可以编写一个自定义序列化程序,但似乎不必如此。
编辑:当我手动序列化我的 Foo
时,我没有使用默认的 OData 序列化器,我使用的是新的 Newtonsoft JsonSerializer。默认的 OData 序列化器和反序列化器根本不喜欢 Object
类型的属性.
最佳答案
我搞定了。 This帖子有帮助。作为 OData 的新手,阅读文档需要一段时间,因为其中大部分都已过时。
在我的 WebApiConfig.cs
中,我使用了将 ODataSerializerProvider
注入(inject) OData 的新方法:
config.MapODataServiceRoute("odata", "api/v1", b =>
b.AddService(ServiceLifetime.Singleton, sp => builder.GetEdmModel())
.AddService<ODataSerializerProvider>(ServiceLifetime.Singleton, sp => new MySerializerProvider(sp)));
MySerializerProvider:
internal sealed class MySerializerProvider : DefaultODataSerializerProvider
{
private MySerializer _mySerializer;
public MySerializerProvider(IServiceProvider sp) : base(sp)
{
_mySerializer = new MySerializer(this);
}
public override ODataEdmTypeSerializer GetEdmTypeSerializer(IEdmTypeReference edmType)
{
var fullName = edmType.FullName();
if (fullName == "Namespace.Bar")
return _mySerializer;
else
return base.GetEdmTypeSerializer(edmType);
}
}
在我的自定义序列化程序中,我注意到 OData 不会自动将 DateTime
转换为 DateTimeOffset
。我的序列化器:
internal sealed class MySerializer : ODataResourceSerializer
{
public MySerializer(ODataSerializerProvider sp) : base(sp) { }
public override ODataResource CreateResource(SelectExpandNode selectExpandNode, ResourceContext resourceContext)
{
ODataResource resource = base.CreateResource(selectExpandNode, resourceContext);
if (resource != null && resourceContext.ResourceInstance is Bar b)
resource = BarToResource(b);
return resource;
}
private ODataResource BarToResource(Bar b)
{
var odr = new ODataResource
{
Properties = new List<ODataProperty>
{
new ODataProperty
{
Name = "Name",
Value = b.Name
},
new ODataProperty
{
Name = "Value",
Value = b.Value is DateTime dt ? new DateTimeOffset(dt) : b.Value
},
new ODataProperty
{
Name = "Group",
Value = b.Group
},
}
};
return odr;
}
}
我知道这是一个非常具体的问题和答案,但我希望有人觉得它有用。
关于c# - OData V4 无法正确序列化包含 System.Object 属性的 POCO(?)s 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49390968/
你能比较一下属性吗 我想禁用文本框“txtName”。有两种方式 使用javascript,txtName.disabled = true 使用 ASP.NET, 哪种方法更好,为什么? 最佳答案 我
Count 属性 返回一个集合或 Dictionary 对象包含的项目数。只读。 object.Count object 可以是“应用于”列表中列出的任何集合或对
CompareMode 属性 设置并返回在 Dictionary 对象中比较字符串关键字的比较模式。 object.CompareMode[ = compare] 参数
Column 属性 只读属性,返回 TextStream 文件中当前字符位置的列号。 object.Column object 通常是 TextStream 对象的名称。
AvailableSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。 object.AvailableSpace object 应为 Drive 
Attributes 属性 设置或返回文件或文件夹的属性。可读写或只读(与属性有关)。 object.Attributes [= newattributes] 参数 object
AtEndOfStream 属性 如果文件指针位于 TextStream 文件末,则返回 True;否则如果不为只读则返回 False。 object.A
AtEndOfLine 属性 TextStream 文件中,如果文件指针指向行末标记,就返回 True;否则如果不是只读则返回 False。 object.AtEn
RootFolder 属性 返回一个 Folder 对象,表示指定驱动器的根文件夹。只读。 object.RootFolder object 应为 Dr
Path 属性 返回指定文件、文件夹或驱动器的路径。 object.Path object 应为 File、Folder 或 Drive 对象的名称。 说明 对于驱动器,路径不包含根目录。
ParentFolder 属性 返回指定文件或文件夹的父文件夹。只读。 object.ParentFolder object 应为 File 或 Folder 对象的名称。 说明 以下代码
Name 属性 设置或返回指定的文件或文件夹的名称。可读写。 object.Name [= newname] 参数 object 必选项。应为 File 或&
Line 属性 只读属性,返回 TextStream 文件中的当前行号。 object.Line object 通常是 TextStream 对象的名称。 说明 文件刚
Key 属性 在 Dictionary 对象中设置 key。 object.Key(key) = newkey 参数 object 必选项。通常是 Dictionary 
Item 属性 设置或返回 Dictionary 对象中指定的 key 对应的 item,或返回集合中基于指定的 key 的&
IsRootFolder 属性 如果指定的文件夹是根文件夹,返回 True;否则返回 False。 object.IsRootFolder object 应为&n
IsReady 属性 如果指定的驱动器就绪,返回 True;否则返回 False。 object.IsReady object 应为 Drive&nbs
FreeSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。只读。 object.FreeSpace object 应为 Drive 对象的名称。
FileSystem 属性 返回指定的驱动器使用的文件系统的类型。 object.FileSystem object 应为 Drive 对象的名称。 说明 可
Files 属性 返回由指定文件夹中所有 File 对象(包括隐藏文件和系统文件)组成的 Files 集合。 object.Files object&n
我是一名优秀的程序员,十分优秀!