我在启动配置服务中有以下代码:
services.AddMvc(options => options.RespectBrowserAcceptHeader = true)
.AddXmlDataContractSerializerFormatters()
.AddXmlSerializerFormatters()
.AddJsonOptions(o =>
{
o.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
});
以下型号:
public interface ITestInterface
{
string Hello { get; set; }
}
public class TestInput
{
public string IWork { get; set; }
public ITestInterface IDontWork { get; set; }
}
关于我的控制器操作:
public async Task<IActionResult> Update([FromBody]TestInput testInput)
{
}
如果我发送以下JSON:
{
"IWork": "I do work",
"IDontWork": { "Hello": "hi hi" }
}
我正确地填充了IWork,但IDontWork却没有。但是,我的界面被注册为临时服务...我是否需要在JSON选项中设置其他内容或使用我自己的合同解析器?
答案 0 :(得分:1)
但是,我的界面已注册为临时服务......
是的,但JSON.Net未与ASP.Net核心依赖注入集成。因此,反序列化器不知道如何创建ITestInterface
的实例。
我是否需要在JSON选项中设置其他内容或使用我自己的合约解析器。
是的,您应该付出一些努力来覆盖这种情况,而自定义合同解析器似乎是最合适的方式。您应采取的步骤如下:
定义自定义合约解析程序。
您可以将其基于JSON.Net使用的DefaultContractResolver
。您应该将IServiceProvider
的实例传递给此解析器,该解析器将用于实例化已注册的类型。
在Startup.ConfigureServices()
中注册JSON.Net反序列化期间合同解析程序可以使用的所有类型。
创建自定义合约解析程序的实例并将其设置为SerializerSettings.ContractResolver
。在Startup.ConfigureServices()
中,您还无权访问IServiceProvider
,因为它尚未创建(因为服务仍在注册)。但是,您可以通过调用services.BuildServiceProvider()
自行创建它。但请确保在此次通话前已注册所有必需的服务。
以下是执行所有描述步骤的示例:
DependencyInjectionContractResolver类:
public class DependencyInjectionContractResolver : DefaultContractResolver
{
private readonly IServiceProvider serviceProvider;
private readonly List<Type> registeredTypes;
public DependencyInjectionContractResolver(IServiceProvider serviceProvider, IEnumerable<Type> registeredTypes)
{
this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
this.registeredTypes = registeredTypes?.ToList() ?? throw new ArgumentNullException(nameof(registeredTypes));
}
protected override JsonContract CreateContract(Type objectType)
{
JsonContract contract = base.CreateContract(objectType);
if (registeredTypes.Contains(objectType))
{
contract.DefaultCreator = () => serviceProvider.GetService(objectType);
}
return contract;
}
}
Startup.ConfigureServices(IServiceCollection services)方法:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ITestInterface, TestClass>();
// Register all other services here
// ...
services.AddMvc(options => options.RespectBrowserAcceptHeader = true)
.AddXmlDataContractSerializerFormatters()
.AddXmlSerializerFormatters()
.AddJsonOptions(o =>
{
o.SerializerSettings.ContractResolver = new DependencyInjectionContractResolver(services.BuildServiceProvider(),
new[] { typeof(ITestInterface) } );
o.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
});
}