NancyFx - 部分绑定
NancyFx - Partial BindTo
我正在尝试使用 NancyFx 实现一种部分更新。
我有一个名为 Resource
的 class,如下所示:
public class Resource
{
public int Id { get; set; }
public decimal SomeValue { get; set; }
public bool Enabled { get; set; }
public DateTime CreationDate { get; set; }
}
我当前的资源实例包含以下值:
{
"Id" : 123,
"SomeValue" : 6,
"Enabled" : true,
"CreationDate" : "2015-08-01T13:00:00"
}
我希望我的 PUT 方法接收一个 JSON 只表示 Resource
的一些属性,例如:
{
"Id": 123,
"SomeValue" : 54.34
}
然后,我会做一个 BindTo(myCurrentResourceInstance)
,结果将是:
{
"Id" : 123,
"SomeValue" : 54.34,
"Enabled" : true,
"CreationDate" : "2015-08-01T13:00:00"
}
但是,我得到这个:
{
"Id" : 123,
"SomeValue" : 54.34,
"Enabled" : false,
"CreationDate" : "0001-01-01T00:00:00"
}
JSON 中包含的属性会正确覆盖当前实例中的属性,但 BindTo()
方法也会更改我未在 JSON 中指定的属性。我只想覆盖 JSON 中指定的属性;其他的应该保持不变。
BindTo()
接收一个 BindingConfig
作为参数,它有一个 Overwrite
属性 (https://github.com/NancyFx/Nancy/wiki/Model-binding)。当这个 属性 为真时,它会导致 BindTo()
覆盖所有属性;当它为 false 时,none 被覆盖。
有什么方法可以实现我想要的吗?
谢谢
由于您希望在 JSON 中未指定时防止当前值被默认值覆盖,您可以将未定义的值列入黑名单:
BindTo<TModel>(this INancyModule module, TModel instance, params string[] blacklistedProperties)` extension method
有了这个,我们可以通过反射提取 属性 列表并排除在 JSON 上定义的列表,并将其传递给该方法:
var definedProperties = JsonConvert
.DeserializeObject<JObject>(json)
.Properties()
.Select(p => p.Name);
var allProperties = typeof(Resource)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Select(p => p.Name);
module.BindTo(myCurrentResourceInstance, allProperties.Except(definedProperties));
我在 github 上查看了 Nancy 的源代码,但我找不到任何公开 JSON 属性 列表的内容,而且它们的序列化程序也是内部的。因此,您将不得不包含另一个库来进行解析(我使用 Newtonsoft.Json)。
我希望您能够以某种方式访问您的 json 以检索 属性 列表。因为我无法在 INancyModule 上找到它,但我猜你确实可以从更高层访问它。
我已经使用 Newtonsoft.Json 成功地完成了我的部分更新。它不像我想要的那样干净,但至少它有效。
var partialResourceAsJson = Request.Body.AsString();
JsonConvert.PopulateObject(partialResourceAsJson, myCurrentResourceInstance);
我正在尝试使用 NancyFx 实现一种部分更新。
我有一个名为 Resource
的 class,如下所示:
public class Resource
{
public int Id { get; set; }
public decimal SomeValue { get; set; }
public bool Enabled { get; set; }
public DateTime CreationDate { get; set; }
}
我当前的资源实例包含以下值:
{
"Id" : 123,
"SomeValue" : 6,
"Enabled" : true,
"CreationDate" : "2015-08-01T13:00:00"
}
我希望我的 PUT 方法接收一个 JSON 只表示 Resource
的一些属性,例如:
{
"Id": 123,
"SomeValue" : 54.34
}
然后,我会做一个 BindTo(myCurrentResourceInstance)
,结果将是:
{
"Id" : 123,
"SomeValue" : 54.34,
"Enabled" : true,
"CreationDate" : "2015-08-01T13:00:00"
}
但是,我得到这个:
{
"Id" : 123,
"SomeValue" : 54.34,
"Enabled" : false,
"CreationDate" : "0001-01-01T00:00:00"
}
JSON 中包含的属性会正确覆盖当前实例中的属性,但 BindTo()
方法也会更改我未在 JSON 中指定的属性。我只想覆盖 JSON 中指定的属性;其他的应该保持不变。
BindTo()
接收一个 BindingConfig
作为参数,它有一个 Overwrite
属性 (https://github.com/NancyFx/Nancy/wiki/Model-binding)。当这个 属性 为真时,它会导致 BindTo()
覆盖所有属性;当它为 false 时,none 被覆盖。
有什么方法可以实现我想要的吗?
谢谢
由于您希望在 JSON 中未指定时防止当前值被默认值覆盖,您可以将未定义的值列入黑名单:
BindTo<TModel>(this INancyModule module, TModel instance, params string[] blacklistedProperties)` extension method
有了这个,我们可以通过反射提取 属性 列表并排除在 JSON 上定义的列表,并将其传递给该方法:
var definedProperties = JsonConvert
.DeserializeObject<JObject>(json)
.Properties()
.Select(p => p.Name);
var allProperties = typeof(Resource)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Select(p => p.Name);
module.BindTo(myCurrentResourceInstance, allProperties.Except(definedProperties));
我在 github 上查看了 Nancy 的源代码,但我找不到任何公开 JSON 属性 列表的内容,而且它们的序列化程序也是内部的。因此,您将不得不包含另一个库来进行解析(我使用 Newtonsoft.Json)。
我希望您能够以某种方式访问您的 json 以检索 属性 列表。因为我无法在 INancyModule 上找到它,但我猜你确实可以从更高层访问它。
我已经使用 Newtonsoft.Json 成功地完成了我的部分更新。它不像我想要的那样干净,但至少它有效。
var partialResourceAsJson = Request.Body.AsString();
JsonConvert.PopulateObject(partialResourceAsJson, myCurrentResourceInstance);