【问题标题】: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 路由值放入 M​​odel/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 值。

      为了满足您的要求,您可以在模型绑定之前修改请求正文,步骤如下:

      1. 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);
                    }
        
                }            
            }
        }
        
      2. 注册ModelResourceFilterAttribute

        services.AddMvc(options =>
        {
            options.Filters.Add(typeof(ModelResourceFilterAttribute));
        }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多