成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術(shù)文章
文章詳情頁

如何在?ASP.NET?Core?Web?API?中處理?Patch?請(qǐng)求

瀏覽:18日期:2022-06-14 15:06:01
目錄一、概述二、將 Keys 保存在 Input Model 中三、定義 ModelBinderFactory 和 ModelBinder四、在 ASP.NET Core 項(xiàng)目中替換 ModelBinderFactory五、定義 AutoMapper 的 TypeConverter六、模型映射七、測試源碼參考資料一、概述

PUT 和 PATCH 方法用于更新現(xiàn)有資源。 它們之間的區(qū)別是,PUT 會(huì)替換整個(gè)資源,而 PATCH 僅指定更改。

在 ASP.NET Core Web API 中,由于 C# 是一種靜態(tài)語言(dynamic 在此不表),當(dāng)我們定義了一個(gè)類型用于接收 HTTP Patch 請(qǐng)求參數(shù)的時(shí)候,在 Action 中無法直接從實(shí)例中得知客戶端提供了哪些參數(shù)。

比如定義一個(gè)輸入模型和數(shù)據(jù)庫實(shí)體:

public class PersonInput{ public string? Name { get; set; } public int? Age { get; set; } public string? Gender { get; set; }}public class PersonEntity{ public string Name { get; set; } public int Age { get; set; } public string Gender { get; set; }}

再定義一個(gè)以 FromForm 形式接收參數(shù)的 Action:

[HttpPatch][Route('patch')]public ActionResult Patch([FromForm] PersonInput input){ // 測試代碼暫時(shí)將 AutoMapper 配置放在方法內(nèi)。 var config = new MapperConfiguration(cfg => {cfg.CreateMap<PersonInput, PersonEntity>()); }); var mapper = config.CreateMapper(); // entity 從數(shù)據(jù)庫讀取,這里僅演示。 var entity = new PersonEntity {Name = '姓名', // 可能會(huì)被改變Age = 18, // 可能會(huì)被改變Gender = '我可能會(huì)被改變', }; // 如果客戶端只輸入 Name 字段,entity 的 Age 和 Gender 將不能被正確映射或被置為 null。 mapper.Map(input, entity); return Ok();}curl --location --request PATCH 'http://localhost:5094/test/patch' \--form 'Name='foo''

如果客戶端只提供了 Name 而沒有其他參數(shù),從 HttpContext.Request.Form.Keys 可以得知這一點(diǎn)。如果不使用 AutoMapper,那么接下來是丑陋的判斷:

var keys = _httpContextAccessor.HttpContext.Request.Form.Keys;if(keys.Contains('Name')){ // 更新 Name(這里忽略合法性判斷) entity.Name = input.Name!;}if (keys.Contains('Age')){ // 更新 Age(這里忽略合法性判斷) entity.Age = input.Age!;}// ...

本文提供一種方式來簡化這個(gè)步驟。

二、將 Keys 保存在 Input Model 中

定義一個(gè)名為 PatchInput 的類:

public abstract class PatchInput{ [BindNever] public ICollection<string>? PatchKeys { get; set; }}

PatchKeys 屬性不由客戶端提供,不參與默認(rèn)綁定。

PersonInput 繼承自 PatchInput:

public class PersonInput : PatchInput{ public string? Name { get; set; } public int? Age { get; set; } public string? Gender { get; set; }}三、定義 ModelBinderFactory 和 ModelBinderpublic class PatchModelBinder : IModelBinder{ private readonly IModelBinder _internalModelBinder; public PatchModelBinder(IModelBinder internalModelBinder) {_internalModelBinder = internalModelBinder; } public async Task BindModelAsync(ModelBindingContext bindingContext) {await _internalModelBinder.BindModelAsync(bindingContext);if (bindingContext.Model is PatchInput model){ // 將 Form 中的 Keys 保存在 PatchKeys 中 model.PatchKeys = bindingContext.HttpContext.Request.Form.Keys;} }}public class PatchModelBinderFactory : IModelBinderFactory{ private ModelBinderFactory _modelBinderFactory; public PatchModelBinderFactory(IModelMetadataProvider metadataProvider,IOptions<MvcOptions> options,IServiceProvider serviceProvider) {_modelBinderFactory = new ModelBinderFactory(metadataProvider, options, serviceProvider); } public IModelBinder CreateBinder(ModelBinderFactoryContext context) {var modelBinder = _modelBinderFactory.CreateBinder(context);// ComplexObjectModelBinder 是 internal 類if (typeof(PatchInput).IsAssignableFrom(context.Metadata.ModelType) && modelBinder.GetType().ToString().EndsWith('ComplexObjectModelBinder')){ modelBinder = new PatchModelBinder(modelBinder);}return modelBinder; }}四、在 ASP.NET Core 項(xiàng)目中替換 ModelBinderFactoryvar builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddPatchMapper();

AddPatchMapper 是一個(gè)簡單的擴(kuò)展方法:

public static class PatchMapperExtensions{ public static IServiceCollection AddPatchMapper(this IServiceCollection services) {services.Replace(ServiceDescriptor.Singleton<IModelBinderFactory, PatchModelBinderFactory>());return services; }}

到目前為止,在 Action 中已經(jīng)能獲取到請(qǐng)求的 Key 了。

[HttpPatch][Route('patch')]public ActionResult Patch([FromForm] PersonInput input){ // 不需要手工給 input.PatchKeys 賦值。 return Ok();}

PatchKeys 的作用是利用 AutoMapper。

五、定義 AutoMapper 的 TypeConverterpublic class PatchConverter<T> : ITypeConverter<PatchInput, T> where T : new(){ /// <inheritdoc /> public T Convert(PatchInput source, T destination, ResolutionContext context) {destination ??= new T();var sourceType = source.GetType();var destinationType = typeof(T);foreach (var key in source.PatchKeys ?? Enumerable.Empty<string>()){ var sourcePropertyInfo = sourceType.GetProperty(key, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); if (sourcePropertyInfo != null) {var destinationPropertyInfo = destinationType.GetProperty(key, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);if (destinationPropertyInfo != null){ var sourceValue = sourcePropertyInfo.GetValue(source); destinationPropertyInfo.SetValue(destination, sourceValue);} }}return destination; }}

上述代碼可用其他手段來代替反射。

六、模型映射[HttpPatch][Route('patch')]public ActionResult Patch([FromForm] PersonInput input){ // 1. 目前僅支持 `FromForm`,即 `x-www-form_urlencoded` 和 `form-data`;暫不支持 `FromBody` 如 `raw` 等。 // 2. 使用 ModelBinderFractory 創(chuàng)建 ModelBinder 而不是 ModelBinderProvider 以便于未來支持更多的輸入格式。 // 3. 目前還沒有支持多級(jí)結(jié)構(gòu)。 // 4. 測試代碼暫時(shí)將 AutoMapper 配置放在方法內(nèi)。 var config = new MapperConfiguration(cfg => {cfg.CreateMap<PersonInput, PersonEntity>().ConvertUsing(new PatchConverter<PersonEntity>()); }); var mapper = config.CreateMapper(); // PersonEntity 有 3 個(gè)屬性,客戶端如果提供的參數(shù)參數(shù)不足 3 個(gè),在 Map 時(shí)未提供參數(shù)的屬性值不會(huì)被改變。 var entity = new PersonEntity {Name = '姓名',Age = 18,Gender = '如果客戶端沒有提供本參數(shù),那我的值不會(huì)被改變' }; mapper.Map(input, entity); return Ok();}七、測試curl --location --request PATCH 'http://localhost:5094/test/patch' \--form 'Name='foo''

curl --location --request PATCH 'http://localhost:5094/test/patch' \--header 'Content-Type: application/x-www-form-urlencoded' \--data-urlencode 'Name=foo'源碼

Tubumu.PatchMapper

支持 FromForm,即 x-www-form_urlencoded 和 form-data。支持 FromBody 如 raw 等。支持多級(jí)結(jié)構(gòu)。參考資料

GraphQL.NET

如何在 ASP.NET Core Web API 中處理 JSON Patch 請(qǐng)求

到此這篇關(guān)于在 ASP.NET Core Web API 中處理 Patch 請(qǐng)求的文章就介紹到這了,更多相關(guān)ASP.NET Core Web API 處理 Patch 請(qǐng)求內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: ASP.NET
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
欧美成人女星排行榜| 午夜精品一区二区三区四区| 成人美女视频在线观看| 欧美日韩综合在线免费观看| 一区二区三区四区不卡视频| 亚洲区第一页| 亚洲色图欧美在线| 韩日视频一区| 亚洲欧洲国产日韩| 伊人久久成人| 中文字幕亚洲区| 亚洲动漫精品| 亚洲色图欧美偷拍| 夜久久久久久| 一区二区三区欧美在线观看| 国产欧美91| 亚洲一区视频在线| 久久久综合网| 麻豆精品在线看| 欧美色图一区二区三区| 麻豆一区二区在线| 欧美一区二视频| 成人avav影音| 国产欧美日韩久久| 亚洲区欧美区| 亚洲电影一区二区三区| 久久久噜噜噜久久狠狠50岁| 老司机午夜精品| 91精品国产综合久久福利| 国产高清不卡二三区| 欧美精品一区二区三区很污很色的 | 日本欧美加勒比视频| 久久久精品五月天| 久久精品国产亚洲a| 欧美一区二区黄色| 91麻豆高清视频| 亚洲男同性恋视频| 性感少妇一区| 免费黄网站欧美| 91精品欧美久久久久久动漫| kk眼镜猥琐国模调教系列一区二区| 久久久精品tv| 亚洲精品1区| 一区二区三区在线视频观看58| 久久精品卡一| 国产一区二区视频在线| 久久久午夜电影| 99riav国产精品| 日韩精品一级二级 | 欧美日韩一区二区三区四区五区 | 成人丝袜高跟foot| 91久久一区二区| 亚洲激情中文1区| 久久精品一区二区三区中文字幕| 男女男精品视频| 51精品秘密在线观看| 国产在线不卡一区| 欧美色综合网站| 亚洲成av人片在线| 亚洲片区在线| 亚洲精选视频免费看| 欧美视频网站| 成人久久视频在线观看| 欧美激情一区二区三区全黄| 国产精品夜夜夜| 国产在线精品免费av| 日韩欧美国产麻豆| 极品少妇一区二区三区| 日本成人在线网站| 久久综合久久鬼色中文字| 日韩一级大片| 国产精品自拍毛片| 国产精品入口麻豆九色| 色丁香久综合在线久综合在线观看| 成人一级片网址| 亚洲在线一区二区三区| 欧美一级理论性理论a| 精品电影一区| 国产一区二区三区在线观看精品| 国产精品美女久久久久久久久 | 久久影院亚洲| 99久久久久久| 日日摸夜夜添夜夜添精品视频| 在线播放视频一区| 亚洲国产一区在线| 国产河南妇女毛片精品久久久| 国产精品国产三级国产普通话99 | 欧美一级精品在线| 99视频精品| 丁香网亚洲国际| 亚洲激情五月婷婷| 欧美一级日韩不卡播放免费| 亚洲少妇诱惑| 99天天综合性| 喷白浆一区二区| 国产精品青草久久| 欧美精品1区2区3区| 国产精品丝袜xxxxxxx| 成人av网站大全| 天堂在线亚洲视频| 国产精品婷婷午夜在线观看| 欧美精品色综合| av不卡在线看| 懂色av一区二区夜夜嗨| 亚洲成人av福利| 欧美激情艳妇裸体舞| 欧美丝袜第三区| 亚洲国产精选| 成人ar影院免费观看视频| 亚洲超碰97人人做人人爱| 久久精品亚洲精品国产欧美kt∨ | 日本福利一区二区| 欧美视频不卡| 激情综合亚洲精品| 樱桃国产成人精品视频| 精品成人佐山爱一区二区| 欧美一级二区| 欧美精品首页| 国产激情精品久久久第一区二区| 亚洲国产综合色| 国产精品久久久久久久久免费桃花 | 美女视频第一区二区三区免费观看网站 | 男女男精品视频| 国产精品国产三级国产aⅴ原创| 91精品国产综合久久久久久久| 亚洲欧美日韩视频二区| 黄色成人91| 9色porny自拍视频一区二区| 久久精品国产亚洲一区二区三区| 亚洲一区二区黄色| 国产精品乱人伦中文| 欧美电影免费提供在线观看| 日本黄色一区二区| 亚洲精品九九| 欧美日韩视频一区二区三区| 成人av资源站| 国产精品一区二区久久不卡| 日韩精品亚洲专区| 亚洲一区二区在线观看视频| 日韩伦理av电影| 中文字幕欧美三区| 久久午夜电影网| 日韩欧美国产成人一区二区| 欧美视频一区二区三区四区| 久久xxxx精品视频| 国产日韩欧美二区| 亚洲黄色三级| 国内精品久久久久久久97牛牛| 国产精品12区| 精品一区二区精品| 免费国产亚洲视频| 日韩中文字幕一区二区三区| 亚洲国产精品一区二区久久| 国产色婷婷亚洲99精品小说| 久久这里都是精品| 26uuu亚洲| 精品国产免费一区二区三区香蕉| 欧美一卡二卡在线观看| 欧美老年两性高潮| 欧美在线啊v一区| 在线观看日韩高清av| 色偷偷成人一区二区三区91| 久久久7777| 每日更新成人在线视频| 久久国产日韩| 久久亚洲色图| 久久综合五月| 在线一区二区三区四区五区| 在线一区二区三区做爰视频网站| 色天天综合色天天久久| 久久精品日产第一区二区 | 国产色爱av资源综合区| 久久女同精品一区二区| 精品剧情在线观看| 精品卡一卡二卡三卡四在线| 日韩亚洲国产中文字幕欧美| 欧美一区二区三区视频在线观看| 欧美一区二区三区公司| 2021国产精品久久精品| 国产亚洲一区二区三区在线观看 | 国产精品家庭影院| 亚洲欧美色一区| 一级特黄大欧美久久久| 午夜不卡在线视频| 美女视频网站黄色亚洲| 国产一区二区h| 成人久久视频在线观看| 99久久伊人精品| 欧美激情五月| 99精品国产高清一区二区| 亚洲欧美日韩国产一区| 91久久精品一区二区二区| 在线不卡的av| 国产视频一区二区在线| 亚洲毛片av在线| 秋霞电影网一区二区| 国产91综合网| 欧美日韩亚洲一区| 国产精品视频免费观看| 欧美揉bbbbb揉bbbbb|