使用 OData 在 aspnet Core 中自定义参数绑定属性
Custom parameter binding attributes in aspnet Core with OData
我在此处发布了 Ricks "raw request body" 属性的实现...
...我正在将解决方案转换为 .Net Core...
有谁知道如何在 aspNet Core 中将其作为 OData 控制器参数的绑定属性来实现?
编辑:
如果它对任何人有帮助,这是我正在尝试转换的代码...
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Core.Api
{
/// <summary>
/// An attribute that captures the entire content body and stores it
/// into the parameter of type byte[].
/// </summary>
/// <remarks>
/// The parameter marked up with this attribute should be the only parameter as it reads the
/// entire request body and assigns it to that parameter.
/// </remarks>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public sealed class RawBodyAttribute : ParameterBindingAttribute
{
public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
{
if (parameter == null) throw new ArgumentException("Invalid parameter");
return new RawBodyParameterBinding(parameter);
}
}
public class RawBodyParameterBinding : HttpParameterBinding
{
public RawBodyParameterBinding(HttpParameterDescriptor descriptor) : base(descriptor) { }
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
{
var binding = actionContext.ActionDescriptor.ActionBinding;
if(binding.ParameterBindings.Count(pb => pb.GetType() == typeof(RawBodyParameterBinding)) != 1)
throw new InvalidOperationException("Exactly one parameter must be marked with the RawBody attribute in the action signature.");
var type = binding.ParameterBindings.First(pb => pb.GetType() == typeof(RawBodyParameterBinding)).Descriptor.ParameterType;
if (type == typeof(string))
{
return actionContext.Request.Content
.ReadAsStringAsync()
.ContinueWith((task) => SetValue(actionContext, task.Result));
}
else if(type == typeof(byte[]))
{
return actionContext.Request.Content
.ReadAsByteArrayAsync()
.ContinueWith((task) => SetValue(actionContext, task.Result));
}
throw new InvalidOperationException("Only byte[] or string values are supported for [RawBody] parameters");
}
public override bool WillReadBody
{
get { return true; }
}
}
}
您需要实现自己的属性和绑定器。
RawBodyAttribute
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class RawBodyAttribute : Attribute, IBindingSourceMetadata
{
public BindingSource BindingSource => RawBodyBindingSource.RawBody;
}
RawBodyBindingSource
public class RawBodyBindingSource : BindingSource
{
public static readonly BindingSource RawBody = new RawBodyBindingSource(
"RawBody",
"RawBody",
true,
true
);
public RawBodyBindingSource(string id, string displayName, bool isGreedy, bool isFromRequest)
: base(id, displayName, isGreedy, isFromRequest)
{
}
public override bool CanAcceptDataFrom(BindingSource bindingSource)
{
return bindingSource == Body || bindingSource == this;
}
}
RawBodyModelBinder
public class RawBodyModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
using (StreamReader reader = new StreamReader(bindingContext.HttpContext.Request.Body, Encoding.UTF8))
{
var model = reader.ReadToEnd();
bindingContext.Result = ModelBindingResult.Success(model);
}
return Task.CompletedTask;
}
}
RawBodyModelBinderProvider
public class RawBodyModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context.BindingInfo.BindingSource != null
&& context.BindingInfo.BindingSource.CanAcceptDataFrom(RawBodyBindingSource.RawBody))
{
return new RawBodyModelBinder();
}
else
{
return null;
}
}
}
注册
services.AddMvc(options =>
{
options.ModelBinderProviders.Insert(0, new RawBodyModelBinderProvider());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
用例
public IActionResult Post([RawBody]string value)
{
return Ok(value);
}
我在此处发布了 Ricks "raw request body" 属性的实现...
...我正在将解决方案转换为 .Net Core...
有谁知道如何在 aspNet Core 中将其作为 OData 控制器参数的绑定属性来实现?
编辑:
如果它对任何人有帮助,这是我正在尝试转换的代码...
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Core.Api
{
/// <summary>
/// An attribute that captures the entire content body and stores it
/// into the parameter of type byte[].
/// </summary>
/// <remarks>
/// The parameter marked up with this attribute should be the only parameter as it reads the
/// entire request body and assigns it to that parameter.
/// </remarks>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public sealed class RawBodyAttribute : ParameterBindingAttribute
{
public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
{
if (parameter == null) throw new ArgumentException("Invalid parameter");
return new RawBodyParameterBinding(parameter);
}
}
public class RawBodyParameterBinding : HttpParameterBinding
{
public RawBodyParameterBinding(HttpParameterDescriptor descriptor) : base(descriptor) { }
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
{
var binding = actionContext.ActionDescriptor.ActionBinding;
if(binding.ParameterBindings.Count(pb => pb.GetType() == typeof(RawBodyParameterBinding)) != 1)
throw new InvalidOperationException("Exactly one parameter must be marked with the RawBody attribute in the action signature.");
var type = binding.ParameterBindings.First(pb => pb.GetType() == typeof(RawBodyParameterBinding)).Descriptor.ParameterType;
if (type == typeof(string))
{
return actionContext.Request.Content
.ReadAsStringAsync()
.ContinueWith((task) => SetValue(actionContext, task.Result));
}
else if(type == typeof(byte[]))
{
return actionContext.Request.Content
.ReadAsByteArrayAsync()
.ContinueWith((task) => SetValue(actionContext, task.Result));
}
throw new InvalidOperationException("Only byte[] or string values are supported for [RawBody] parameters");
}
public override bool WillReadBody
{
get { return true; }
}
}
}
您需要实现自己的属性和绑定器。
RawBodyAttribute
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public class RawBodyAttribute : Attribute, IBindingSourceMetadata { public BindingSource BindingSource => RawBodyBindingSource.RawBody; }
RawBodyBindingSource
public class RawBodyBindingSource : BindingSource { public static readonly BindingSource RawBody = new RawBodyBindingSource( "RawBody", "RawBody", true, true ); public RawBodyBindingSource(string id, string displayName, bool isGreedy, bool isFromRequest) : base(id, displayName, isGreedy, isFromRequest) { } public override bool CanAcceptDataFrom(BindingSource bindingSource) { return bindingSource == Body || bindingSource == this; } }
RawBodyModelBinder
public class RawBodyModelBinder : IModelBinder { public Task BindModelAsync(ModelBindingContext bindingContext) { using (StreamReader reader = new StreamReader(bindingContext.HttpContext.Request.Body, Encoding.UTF8)) { var model = reader.ReadToEnd(); bindingContext.Result = ModelBindingResult.Success(model); } return Task.CompletedTask; } }
RawBodyModelBinderProvider
public class RawBodyModelBinderProvider : IModelBinderProvider { public IModelBinder GetBinder(ModelBinderProviderContext context) { if (context.BindingInfo.BindingSource != null && context.BindingInfo.BindingSource.CanAcceptDataFrom(RawBodyBindingSource.RawBody)) { return new RawBodyModelBinder(); } else { return null; } } }
注册
services.AddMvc(options => { options.ModelBinderProviders.Insert(0, new RawBodyModelBinderProvider()); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
用例
public IActionResult Post([RawBody]string value) { return Ok(value); }