【问题标题】:Attribute Routing Values into Model/FromBody Parameter in ASP.NET CORE属性路由值到 ASP.NET CORE 中的模型/FromBody 参数
【发布时间】:2019-07-11 15:18:10
【问题描述】:
我正在开发一个 .NET 核心 Web API 应用程序,我希望将 URL 路由值放入 Model/FromBody 参数中。如果 From body 模型中存在路由属性。
是否有任何通用解决方案,即适用于所有模型类型。
我们已经找到了自定义模型绑定器,但它适用于特定于模型类型。我正在寻找适用于所有模型类型的自定义模型绑定器。
例如:
Action route: [Route("AH/{userId}")]
Url : ../AH/123
From body:
{
"userId":"",
"Value" : "Some value"
}
现在需要将路由值 123 映射到 FromBody 模型属性“userId”
【问题讨论】:
标签:
c#
.net-core
asp.net-core-webapi
modelbinders
custom-model-binder
【解决方案1】:
您不能从请求正文中填充路由参数。路由参数是 URL 的一部分,因此必须独立于实际发布的正文而存在。
无论如何,您永远不应相信来自发布请求正文的 ID 之类的东西。始终从 URL 获取该信息。 URL 定义了一个唯一资源,因此到该 URL 的帖子只能影响该唯一资源。如果您依赖帖子正文,则恶意用户可以操纵发布的值,从而可能更改他们不应访问的资源。
【解决方案2】:
对于您当前的请求,"userId":"" 将使请求失败,因为 "" 无法转换为 int 值。
为了满足您的要求,您可以在模型绑定之前修改请求正文,步骤如下:
-
ModelResourceFilterAttribute
public class ModelResourceFilterAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
public void OnResourceExecuting(ResourceExecutingContext context)
{
context.HttpContext.Request.EnableRewind();
var routeData = context.RouteData;
var stream = context.HttpContext.Request.Body;
using (var streamReader = new StreamReader(context.HttpContext.Request.Body))
{
var json = streamReader.ReadToEnd();
if (json != "")
{
var jsonObj = JObject.Parse(json);
foreach (var item in routeData.Values)
{
JToken token;
if (jsonObj.TryGetValue(
item.Key,
StringComparison.InvariantCultureIgnoreCase,
out token))
{
var jProperty = token.Parent as JProperty;
if (jProperty != null)
{
jProperty.Value = item.Value.ToString();
}
}
}
var body = jsonObj.ToString(Formatting.Indented);
byte[] byteArray = Encoding.UTF8.GetBytes(body);
//byte[] byteArray = Encoding.ASCII.GetBytes(contents);
context.HttpContext.Request.Body = new MemoryStream(byteArray);
}
}
}
}
-
注册ModelResourceFilterAttribute
services.AddMvc(options =>
{
options.Filters.Add(typeof(ModelResourceFilterAttribute));
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);