我正在尝试使用ASP.NET中内置的RESTful API从演示数据库中获取信息。为了从数据库中获取信息,我需要通过标头传递一个对象。但是,我的API没有收到这些值。我的API函数正在使用[FromHeader]属性,但没有任何反应。我得到400状态,并显示以下错误消息:{“ AccountEmail”:[“ AccountEmail字段为必填。”]}
这是下面的代码:
我有一个看起来像这样的模型:
{
[Serializable]
public class Account
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Required]
public long AccountId { get; protected set; }
[Required]
[EmailAddress]
public string AccountEmail { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Required]
public Guid AccountAccessKey { get; set; }
}
}
The API call looks like
[HttpGet]
[AccountFilter]
public async Task<ActionResult<Account>> GetAccount([FromHeader] Account account) {
try
{
return await _Context.GetAccount(account.AccountEmail);
}
catch { }
return BadRequest(new Error()
{
ErrorTitle = "Unable to get Account",
ErrorMessage = "ValidationError"
});
}
Where GetAccount looks like
public Task<Account> GetAccount(string email)
{
return _context.Accounts.FirstOrDefaultAsync(x => x.AccountEmail == email);
}
The API call looks like this
let account = new Account({
AccountEmail: 'gazefekini@eaglemail.top',
AccountAccessKey:'00000000-0000-0000-0000-000000000000',
AccountId:0
})
fetch(process.env.API + '/api/Account/GetAccount', {
method:'GET',
headers: {
"Accept":"application/json",
"account": "" + account
}
})
我可以使用FromQuery并通过AccountId获取账户,但是我有一个Filter,它需要AccountAccessKey和AccountEmail在Filter中进行一些AWS验证,因此为什么决定将账户标头传递给api调用。
我尝试在模型中删除AccountEmail的[Required]属性,然后API调用起作用,但是我需要具有[Required]属性。
我想念什么吗?我知道错误是由[Required]属性引起的,但我不确定为什么
答案 0 :(得分:0)
根据您的要求,您需要实现自己的模型绑定程序。
自定义HeaderComplexModelBinder
public class HeaderComplexModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var headerModel = bindingContext.HttpContext.Request.Headers[bindingContext.OriginalModelName].FirstOrDefault();
var modelType = bindingContext.ModelMetadata.ModelType;
bindingContext.Model = JsonConvert.DeserializeObject(headerModel, modelType);
bindingContext.Result = ModelBindingResult.Success(bindingContext.Model);
return Task.CompletedTask;
}
}
自定义IModelBinderProvider
public class HeaderComplexModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Metadata.IsComplexType)
{
var x = context.Metadata as Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelMetadata;
var headerAttribute = x.Attributes.Attributes.Where(a => a.GetType() == typeof(FromHeaderAttribute)).FirstOrDefault();
if (headerAttribute != null)
{
return new BinderTypeModelBinder(typeof(HeaderComplexModelBinder));
}
else
{
return null;
}
}
else
{
return null;
}
}
}
在Startup.cs
中配置
services.AddMvc(options => {
options.ModelBinderProviders.Insert(0, new HeaderComplexModelBinderProvider());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);