<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        .NET Core WebApi中如何實現(xiàn)多態(tài)數(shù)據(jù)綁定實例代碼

        來源:懂視網(wǎng) 責編:小采 時間:2020-11-27 22:34:49
        文檔

        .NET Core WebApi中如何實現(xiàn)多態(tài)數(shù)據(jù)綁定實例代碼

        .NET Core WebApi中如何實現(xiàn)多態(tài)數(shù)據(jù)綁定實例代碼:什么是.NET Core? 隨著2014年 Xamarin和微軟發(fā)起.NET基金會,微軟在2014年11月份 開放.NET框架源代碼。在.NET開源基金會的統(tǒng)一規(guī)劃下誕生了.NET Core 。也就是說.NET Core Framework是參考.NET Framework重新開發(fā)的.NET實現(xiàn),Mo
        推薦度:
        導讀.NET Core WebApi中如何實現(xiàn)多態(tài)數(shù)據(jù)綁定實例代碼:什么是.NET Core? 隨著2014年 Xamarin和微軟發(fā)起.NET基金會,微軟在2014年11月份 開放.NET框架源代碼。在.NET開源基金會的統(tǒng)一規(guī)劃下誕生了.NET Core 。也就是說.NET Core Framework是參考.NET Framework重新開發(fā)的.NET實現(xiàn),Mo

        什么是.NET Core?

        隨著2014年 Xamarin和微軟發(fā)起.NET基金會,微軟在2014年11月份 開放.NET框架源代碼。在.NET開源基金會的統(tǒng)一規(guī)劃下誕生了.NET Core 。也就是說.NET Core Framework是參考.NET Framework重新開發(fā)的.NET實現(xiàn),Mono是.NET Framework的一個開源的、跨平臺的實現(xiàn)。

        本文主要介紹了關(guān)于.NET Core WebApi多態(tài)數(shù)據(jù)綁定的相關(guān)內(nèi)容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧

        什么是多態(tài)數(shù)據(jù)綁定?

        我們都知道在ASP.NET Core WebApi中數(shù)據(jù)綁定機制(Data Binding)負責綁定請求參數(shù), 通常情況下大部分的數(shù)據(jù)綁定都能在默認的數(shù)據(jù)綁定器(Binder)中正常的進行,但是也會出現(xiàn)少數(shù)不支持的情況,例如多態(tài)數(shù)據(jù)綁定。所謂的多態(tài)數(shù)據(jù)綁定(polymorphic data binding),即請求參數(shù)是子類對象的Json字符串, 而action中定義的是父類類型的變量,默認情況下ASP.NET Core WebApi是不支持多態(tài)數(shù)據(jù)綁定的,會造成數(shù)據(jù)丟失。

        以下圖為例

        Person類是一個父類,Doctor類和Student類是Person類的派生類。Doctor類中持有的HospitalName屬性,Student中持有的SchoolName屬性。

        接下來我們創(chuàng)建一個Web Api項目并添加一個PeopleController。

        在PeopleController中我們添加一個Add api,并將請求數(shù)據(jù)直接返回,以便查看效果。

        [Route("api/people")]
        public class PeopleController : Controller
        {
         [HttpPost]
         [Route("")]
         public List<Person> Add([FromBody]List<Person> people)
         {
         return people;
         }
        }

        這里我們使用Postman請求這個api, 請求的Content-Type是application/json, 請求的Body內(nèi)容如下。

        [{
         firstName: 'Mike',
         lastName: 'Li'
        }, {
         firstName: 'Stephie',
         lastName: 'Wang',
         schoolName: 'No.15 Middle School'
        }, {
         firstName: 'Jacky',
         lastName: 'Chen',
         hospitalName: 'Center Hospital'
        }]

        請求的返回內(nèi)容

        [
         {
         "FirstName": "Mike",
         "LastName": "Li"
         },
         {
         "FirstName": "Stephie",
         "LastName": "Wang"
         },
         {
         "FirstName": "Jacky",
         "LastName": "Chen"
         }
        ]

        返回結(jié)果和我們希望得到的結(jié)果不太一樣,Student持有的SchoolName屬性和Doctor持有的HospitalName屬性都丟失了。

        現(xiàn)在我們啟動項目調(diào)試模式,重新使用Postman請求一次,得到的結(jié)果如下

        People集合中存放3個People類型的對象, 沒有出現(xiàn)我們期望的Student類型對象和Doctor類型對象,這說明.NET Core WebApi默認是不支持多態(tài)數(shù)據(jù)綁定的,如果使用父類類型變量來接收數(shù)據(jù),Data Binding只會實例化父類對象,而非一個派生類對象, 從而導致屬性丟失。

        自定義JsonConverter來實現(xiàn)多態(tài)數(shù)據(jù)綁定

        JsonConverter是Json.NET中的一個類,主要負責Json對象的序列化和反序列化。

        首先我們創(chuàng)建一個泛型類JsonCreationConverter,并繼承了JsonConverter類,代碼如下:

        public abstract class JsonCreationConverter<T> : JsonConverter
        {
         public override bool CanWrite
         {
         get
         {
         return false;
         }
         }
        
         protected abstract T Create(Type objectType, JObject jObject);
        
         public override bool CanConvert(Type objectType)
         {
         return typeof(T).IsAssignableFrom(objectType);
         }
        
        
         public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
         {
         if (reader == null) throw new ArgumentNullException("reader");
         if (serializer == null) throw new ArgumentNullException("serializer");
         if (reader.TokenType == JsonToken.Null)
         return null;
        
         JObject jObject = JObject.Load(reader);
         T target = Create(objectType, jObject);
         serializer.Populate(jObject.CreateReader(), target);
         return target;
         }
        
         public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
         {
         throw new NotImplementedException();
         }
        }

        其中,我們加入了一個抽象方法Create,這個方法會負責根據(jù)Json字符串的內(nèi)容,返回一個泛型類型對象,這里既可以返回一個當前泛型類型的對象,也可以返回一個當前泛型類型派生類的對象。JObject是Json.NET中的Json字符串讀取器,負責讀取Json字符串中屬性的值。

        另外我們還復寫了ReadJson方法,在ReadJson中我們會先調(diào)用Create方法獲取一個當前泛型類對象或者當前泛型類的派生類對象(Json.NET中默認的KeyValuePairConverter會直接實例化當前參數(shù)類型對象,這也就是默認不支持多態(tài)數(shù)據(jù)綁定的主要原因),serializer.Popluate方法的作用是將Json字符串的內(nèi)容映射到目標對象(當前泛型類對象或者當前泛型類的派生類對象)的對應(yīng)屬性。

        這里由于我們只需要讀取Json, 所以WriteJson的方法我們不需要實現(xiàn),CanWrite屬性我們也強制返回了False。

        第二步,我們創(chuàng)建一個PersonJsonConverter類,它繼承了JsonCreationConverter<Person>, 其代碼如下

        public class PersonJsonConverter : JsonCreationConverter<Person>
        {
         protected override Person Create(Type objectType, JObject jObject)
         {
         if (jObject == null) throw new ArgumentNullException("jObject");
        
         if (jObject["schoolName"] != null)
         {
         return new Student();
         }
         else if (jObject["hospitalName"] != null)
         {
         return new Doctor();
         }
         else
         {
         return new Person();
         }
         }
        }

        在這個類中我們復寫了Create方法,這里我們使用JObject來獲取Json字符串中擁有的屬性。

      1. 如果字符串中包含schoolName屬性,就返回一個新的Student對象
      2. 如果字符串中包含hospitalName屬性,就返回一個新的Doctor對象
      3. 否則,返回一個新Person對象
      4. 最后一步,我們在Person類中使用特性標注Person類使用PersonJsonConverter來進行轉(zhuǎn)換Json序列化和反序列化。

        [JsonConverter(typeof(PersonJsonConverter))]
        public class Person
        {
         public string FirstName { get; set; }
        
         public string LastName { get; set; }
        }

        現(xiàn)在我們重新使用調(diào)試模式啟動程序, 然后使用Postman請求當前api

         

        我們會發(fā)現(xiàn),people集合中已經(jīng)正確綁定了的派生子類類型對象,最終Postman上我們得到以下響應(yīng)結(jié)果

        [
         {
         "FirstName": "Mike",
         "LastName": "Li"
         },
         {
         "SchoolName": "No.15 Middle School",
         "FirstName": "Stephie",
         "LastName": "Wang"
         },
         {
         "HospitalName": "Center Hospital",
         "FirstName": "Jacky",
         "LastName": "Chen"
         }
        ]

        至此多態(tài)數(shù)據(jù)綁定成功。

        刨根問底

        為什么添加了一個PersonJsonConverter類,多態(tài)綁定就實現(xiàn)了呢?

        讓我們來一起Review一下MVC Core以及Json.NET的代碼。

        首先我們看一下MvcCoreMvcOptionsSetup代碼

        public class MvcCoreMvcOptionsSetup : IConfigureOptions<MvcOptions>
        {
         private readonly IHttpRequestStreamReaderFactory _readerFactory;
         private readonly ILoggerFactory _loggerFactory;
        
         ......
         
         public void Configure(MvcOptions options)
         {
         options.ModelBinderProviders.Add(new BinderTypeModelBinderProvider());
         options.ModelBinderProviders.Add(new ServicesModelBinderProvider());
         options.ModelBinderProviders.Add(new BodyModelBinderProvider(options.InputFormatters, _readerFactory, _loggerFactory, options));
         ......
         }
        
         ......
         
        }

        MvcCoreMvcOptionsSetup類中的Configure方法設(shè)置了默認數(shù)據(jù)綁定使用Provider列表。

        當一個api參數(shù)被標記為[FromBody]時,BodyModelBinderProvider會實例化一個BodyModelBinder對象來處理這個參數(shù)并嘗試進行數(shù)據(jù)綁定。

        BodyModelBinder類中有一個BindModelAsync方法,從名字的字面意思上我們很清楚的知道這個方法就是用來綁定數(shù)據(jù)的。

        public async Task BindModelAsync(ModelBindingContext bindingContext)
        {
         if (bindingContext == null)
         {
         throw new ArgumentNullException(nameof(bindingContext));
         }
        
         ….
        
         var formatter = (IInputFormatter)null;
         for (var i = 0; i < _formatters.Count; i++)
         {
         if (_formatters[i].CanRead(formatterContext))
         {
         formatter = _formatters[i];
         _logger?.InputFormatterSelected(formatter, formatterContext);
         break;
         }
         else
         {
         logger?.InputFormatterRejected(_formatters[i], formatterContext);
         }
         }
        
         ……
        
         try
         {
         var result = await formatter.ReadAsync(formatterContext);
        
         ……
         }
         catch (Exception exception) when (exception is InputFormatterException || ShouldHandleException(formatter))
         {
         bindingContext.ModelState.AddModelError(modelBindingKey, exception, bindingContext.ModelMetadata);
         }
        }

        在這個方法中它會嘗試尋找一個匹配的IInputFormatter對象來綁定數(shù)據(jù),由于這時候請求的Content-Type是application/json, 所以這里會使用JsonInputFormatter對象來進行數(shù)據(jù)綁定。

        下面我們看一下JsonInputFormatter類的部分關(guān)鍵代碼

        public override async Task<InputFormatterResult> ReadRequestBodyAsync(
         InputFormatterContext context,
         Encoding encoding)
        {
         ......
        
         using (var streamReader = context.ReaderFactory(request.Body, encoding))
         {
         using (var jsonReader = new JsonTextReader(streamReader))
         {
         …
        
         object model;
         try
         {
         model = jsonSerializer.Deserialize(jsonReader, type);
         }
         finally
         {
         jsonSerializer.Error -= ErrorHandler;
         ReleaseJsonSerializer(jsonSerializer);
         }
        
         …
         }
         }
        }

        JsonInputFormatter類中的ReadRequestBodyAsync方法負責數(shù)據(jù)綁定, 在該方法中使用了Json.NET的JsonSerializer類的Deserialize方法來進行反序列化, 這說明Mvc Core的底層是直接使用Json.NET來操作Json的。

        JsonSerializer類的部分關(guān)鍵代碼

        public object Deserialize(JsonReader reader, Type objectType)
        {
         return DeserializeInternal(reader, objectType);
        }
        
        internal virtual object DeserializeInternal(JsonReader reader, Type objectType)
        {
         ……
        
         JsonSerializerInternalReader serializerReader = new JsonSerializerInternalReader(this);
         object value = serializerReader.Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent);
        
         ……
         return value;
        }

        JsonSerializer會調(diào)用JsonSerializerInternalReader類的Deserialize方法將Json字符串內(nèi)容反序列化。

        最終我們看一下JsonSerializerInternalReader中的部分關(guān)鍵代碼

        public object Deserialize(JsonReader reader, Type objectType, bool checkAdditionalContent)
        {
         …
        
         JsonConverter converter = GetConverter(contract, null, null, null);
        
         if (reader.TokenType == JsonToken.None && !reader.ReadForType(contract, converter != null))
         {
         ......
        
         object deserializedValue;
        
         if (converter != null && converter.CanRead)
         {
         deserializedValue = DeserializeConvertable(converter, reader, objectType, null);
         }
         else
         {
         deserializedValue = CreateValueInternal(reader, objectType, contract, null, null, null, null);
         }
         }
        }

        JsonSerializerInternalReader類里面的Deserialize方法會嘗試根據(jù)當前請求參數(shù)的類型,去查找并實例化一個合適的JsonConverter。 如果查找到匹配的Converter, 就使用該Converter進行實際的反序列化數(shù)據(jù)綁定操作。在當前例子中由于api的參數(shù)類型是Person,所以它會匹配到PersonJsonConverter, 這就是為什么我們通過添加PersonJsonConverter就完成了多態(tài)數(shù)據(jù)綁定的功能。

        附源代碼

        總結(jié)

        聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        .NET Core WebApi中如何實現(xiàn)多態(tài)數(shù)據(jù)綁定實例代碼

        .NET Core WebApi中如何實現(xiàn)多態(tài)數(shù)據(jù)綁定實例代碼:什么是.NET Core? 隨著2014年 Xamarin和微軟發(fā)起.NET基金會,微軟在2014年11月份 開放.NET框架源代碼。在.NET開源基金會的統(tǒng)一規(guī)劃下誕生了.NET Core 。也就是說.NET Core Framework是參考.NET Framework重新開發(fā)的.NET實現(xiàn),Mo
        推薦度:
        標簽: 綁定 net 實例代碼
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 91情国产l精品国产亚洲区| 国产亚洲情侣一区二区无码AV| 日韩亚洲AV无码一区二区不卡| 国产精品免费看久久久| 亚洲国产精品线在线观看| 久久久久久国产精品免费无码| 亚洲国产理论片在线播放| 成年网站免费视频A在线双飞| 亚洲乱码卡三乱码新区| 免费无码AV片在线观看软件| 亚洲国产欧美国产综合一区| 国产大片线上免费看| 黄色网页免费观看| 亚洲日韩国产精品第一页一区| 永久免费av无码入口国语片| 亚洲视频在线观看地址| www.黄色免费网站| 爱情岛亚洲论坛在线观看| 亚洲国产成人久久综合碰| 18禁超污无遮挡无码免费网站| 久久精品国产亚洲av日韩| 久久久久免费看黄A片APP | 亚洲熟女乱综合一区二区| baoyu122.永久免费视频| 亚洲高清日韩精品第一区| 成年人在线免费看视频| 免费人成动漫在线播放r18| 亚洲精品无码鲁网中文电影| 一级毛片aaaaaa免费看| 亚洲人成网亚洲欧洲无码| 亚洲综合另类小说色区色噜噜| 久久99精品国产免费观看| 亚洲精品无码高潮喷水A片软| 又黄又大又爽免费视频| 免费人妻无码不卡中文字幕系| 亚洲夂夂婷婷色拍WW47| 国产亚洲AV手机在线观看| 毛片免费观看视频| 久久国产乱子伦精品免费午夜 | 亚洲国产aⅴ综合网| 在线日本高清免费不卡|