首页 > 解决方案 > 属性路由值到 ASP.NET CORE 中的模型/FromBody 参数

问题描述

我正在开发一个 .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-coreasp.net-core-webapimodelbinderscustom-model-binder

解决方案


对于您当前的请求,"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);
    

推荐阅读