asp.net core IModelBinder

环境:Windows 10,Visual Studio 2017,ASP.NET Core,.NET Core 2.2
————————————————————————————————————————————————————
最近在做一个项目升级,要把之前.net framework升级到.net core,有用到Action参数绑定(DefaultModelBinder)这个类去做一些东西,因为.net core里面已经没有 DefaultModelBinder 了,所以要改用 IModelBinder。

继承IModelBinder接口,在进行Action参数绑定的时候,每多一个参数,就会执行一次BindModelAsync,但是除了第一次之外就无法通过bindingContext.ActionContext.HttpContext.Request.Body获取传进来的数据,所以要把数据保存起来。(我开发的时候观察到的情况是这样的,不保证正确)

在BindModelAsync里面可以通过ModelBindingContext 获得很多东西,比如:HttpContext、Files、ContentType等。

在做完我们自己的事情后,通过bindingContext.Result = ModelBindingResult.Success(obj);返回数据。

详细的看代码。

IModelBinder接口,自定义参数绑定实现代码

using DevMate.Common;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;
using System.Threading.Tasks;

namespace WSM.Manage.Common
{
	public class CustomModelBinder : IModelBinder
	{
		private readonly object _locker = new object();
		private const string cachekey = "JsonModel";
		private int paramIndex = 0;
		private const string paramIndexKey = "ParamIndex";

		public Task BindModelAsync(ModelBindingContext bindingContext)
		{
			var request = bindingContext.ActionContext.HttpContext.Request;
			if (request.HttpContext.Request.ContentType.ToLower() != "application/json" && request.Form.Files.Count > 0)
				return Task.CompletedTask;

			JObject data = request.HttpContext.Items[cachekey] as JObject;
			if (_data == null)
			{
				using (var sr = new StreamReader(request.Body))
				{
					var json = sr.ReadToEnd();
					data = JsonConvert.DeserializeObject<JObject>(json);
					request.HttpContext.Items[cachekey] = data;
				}
			}


			string Sign = data["Sign"] == null ? null : _data["Sign"].ToString();
			if (string.IsNullOrEmpty(Sign))
				return Task.CompletedTask;

			paramIndex = request.HttpContext.Items[paramIndexKey] == null ? 0 : int.Parse("0" + request.HttpContext.Items[paramIndexKey]);
			string key = "param";
			lock (_locker)
			{
				key = "param" + paramIndex;
				paramIndex++;
				request.HttpContext.Items[paramIndexKey] = paramIndex;
			}

			object obj = null;
			string jsonField = DataConvert.ToString(data[key]);
			if (bindingContext.ModelType == typeof(JArray))
			{
				obj = DataConvert.ToJArray(jsonField);
			}
			else if (bindingContext.ModelType.IsClass || bindingContext.ModelType.IsArray || bindingContext.ModelType.IsGenericType)
			{
				obj = JsonConvert.DeserializeObject(jsonField, bindingContext.ModelType);
			}
			else
			{
				obj = data[key].ToObject(bindingContext.ModelType);
			}
			bindingContext.Result = ModelBindingResult.Success(obj);

			return Task.CompletedTask; 
		}
	}
}

IModelBinderProvider

using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace WSM.Manage.Common
{
	public class CustomModelBinderProvider: IModelBinderProvider
	{
		public IModelBinder GetBinder(ModelBinderProviderContext context)
		{
			return new CustomModelBinder();
		}
    }
}

绑定到ModelBinderProviders,放在第一个

services.AddMvc(options =>
			{
				options.ModelBinderProviders.Insert(0, new CustomModelBinderProvider());
			});

———————————————————————————————————————————————————————
!重大失误

上面说第二次及以后进来拿不到Body的数据,这是不对的,不是拿不到数据,而是第一次读取字节流的时候读到字节流最后的位置,再次读取字节流的时候就拿不到数据,需要重置一下。

———————————————————————————————————————————————————————
2020年7月29日更新
补充一点,GET请求方式的处理方法,可以通过Request.Method判断是那种请求方式,(ModelBindingContext)bindingContext.OriginalModelName 可以获得当前参数名,request.Query[bindingContext.OriginalModelName] 这样就能拿到GET请求传进来的参数值。

		private void HandleGetRequest(ModelBindingContext bindingContext)
		{
			HttpRequest request = bindingContext.ActionContext.HttpContext.Request;
			if (request.Query.Count == 0)
			{
				return;
			}

			bindingContext.Result = ModelBindingResult.Success(request.Query[bindingContext.OriginalModelName] + "");
		}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郑小晨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值