FlexFetcher是一個.NET庫,用於過濾,分類,分頁數據。它是基於OOP原理設計的,可用於任何.NET項目:Web,桌面,移動設備等。 FlexFetcher的靈感來自Telerik Kendo UI網格對象格式。
.NET中有很多很棒的庫,用於過濾,分類,分頁數據:篩,QueryKit,Lightquery等。但是,其中大多數不是基於OOP原理設計的。它們具有旨在可讀的查詢語法,例如(所有示例均來自這些庫文檔):
sorts=LikeCount,CommentCount,-created&filters=LikeCount>10,Title@=awesome title,&page=1&pageSize=10
或者
""(Age ^^ [20, 30, 40]) && (BirthMonth ^^* ["January", "February", "March"]) || (Id ^^ ["6d623e92-d2cf-4496-a2df-f49fa77328ee"])""
或者
`?sort=country&thenSort=email desc`
但同時:
Flexfetcher並不比那些圖書館更好或更糟,這只是不同的。它接受以對象格式的查詢,可以序列化/避免到JSON/從JSON進行序列化:
?Filters={"Logic":"And","Filters":[{"Operator":"Eq","Field":"Address.Town","Value":"New York"}]}
或者,如果您更喜歡更緊湊的格式,即使是這樣:
?Filter={"L":"And","Fs":[{"O":"Eq","F":"Address.Town","V":"New York"}]}
或者,如果您想使用發布請求(RPC樣式),則像這樣:
{
"Filters" : {
"Logic" : " and " ,
"Filters" : [
{
"Operator" : " eq " ,
"Field" : " Address.Town " ,
"Value" : " New York "
}
]
}
}這種格式易於閱讀和理解人類,易於擴展,易於序列化/挑選化,並且易於用於機器對機器通信。
Flexfetcher是為下一個平台構建的:
這意味著您可以在.NET Core(請參閱samples/WebApiSample )和.NET Framework(請參閱samples/WebApiSample.Framework48 )項目中使用它。
FlexFetcher支持用於過濾器和分角中使用的字段的下一個數據類型:
所有值可能都是無效的。
您可以通過運行下一個命令通過Nuget軟件包管理器控制FlexFetcher(Nuget):
dotnet add package FlexFetcher
安裝flexfetcher.ipendendencyindoction.microsoft(nuget):
dotnet add package FlexFetcher.DependencyInjection.Microsoft
安裝flexfetcher.serialization.newtonsoftjson(nuget):
dotnet add package FlexFetcher.Serialization.NewtonsoftJson
安裝FlexFetcher.Serialization.SystemTextjson(Nuget):
dotnet add package FlexFetcher.Serialization.SystemTextJson
所有示例均在測試數據集上完成,該數據集在
tests/TestData/InMemoryDataHelper.cs中定義,由tests/TestData/Database/PeopleEntity.cs和tests/TestData/Database/AddressEntity.cs組成。
利用FlexFetcher的最簡單方法是使用擴展方法進行IQueryable<T>和IEnumerable<T>接口。
var filter = new DataFilter
{
Filters = new List < DataFilter >
{
new ( )
{
Field = "Name" ,
Operator = DataFilterOperator . Equal ,
Value = "John"
}
}
} ;
var result = _ctx . People . FilterData ( filter ) . ToList ( ) ; var sorter = new DataSorters
{
Sorters = new List < DataSorter >
{
new DataSorter // First sort by Surname in ascending order
{
Field = "Surname" ,
Direction = DataSorterDirection . Asc
} ,
new DataSorter // Then sort by Name in descending order
{
Field = "Name" ,
Direction = DataSorterDirection . Desc
}
}
} ;
var result = _ctx . People . SortData ( sorter ) . ToList ( ) ; var pager = new DataPager { PageSize = 3 , Page = 1 } ; // Numeration starts from 1 for Page number
OR
var pager = new DataPager { Skip = 3 , Take = 3 } ;
var result = _ctx . People . PageData ( pager ) . ToList ( ) ; 擴展方法適用於簡單的情況,但是它們的用法非常有限。
For more complex cases you can use FlexFetcher classes: FlexFilter<TEntity> and FlexFilter<TEntity, TModel> , FlexSorter<TEntity> and FlexSorter<TEntity, TModel> , FlexPager<TEntity> and FlexPager<TEntity, TModel> , FlexFetcher<TEntity> and FlexFetcher<TEntity, TModel> .
即使不建議這樣做,但是為了清楚起見,讓我們看看如何手動創建課堂實例。我們將在稍後的相應部分中查看依賴注入。
var filter = new DataFilter
{
Filters = new List < DataFilter >
{
new ( )
{
Field = "Name" ,
Operator = DataFilterOperator . Equal ,
Value = "John"
}
}
} ;
var flexFilter = new FlexFilter < PeopleEntity > ( ) ;
var result = flexFilter . FilterData ( _ctx . People , filter ) . ToList ( ) ; var sorters = new DataSorters
{
Sorters = new List < DataSorter >
{
new DataSorter
{
Field = "Surname" ,
Direction = DataSorterDirection . Asc
}
}
} ;
var flexSorter = new FlexSorter < PeopleEntity > ( ) ;
var result = flexSorter . SortData ( _ctx . People , sorters ) . ToList ( ) ; var pager = new DataPager { PageSize = 3 , Page = 1 } ;
var flexPager = new FlexPager < PeopleEntity > ( ) ;
var result = flexPager . PageData ( _ctx . People , pager ) . ToList ( ) ; var pager = new DataPager { PageSize = 3 , Page = 1 } ;
var flexFetcher = new FlexFetcher < PeopleEntity > ( ) ;
var result = flexFetcher . FetchData ( _ctx . People , null , null , pager ) . ToList ( ) ; // Filter, sorter and pager parameters are optional 為了將FlexFetcher和依賴項注入使用,請不要忘記安裝FlexFetcher.DependencyInjection.Microsoft軟件包。
可以注入主Flexfetcher類及其組件:FlexFilter,Flexsorter,FlexPager。基本用法是:
services . AddSingleton < FlexFetcher < PeopleEntity > > ( ) ;Flexfetcher課程沒有任何狀態,因此可以安全地將其用作單例。但是,如果您想將它們用作範圍或瞬態,則取決於您。
接下來將顯示更高級的方案填充。另外samples/WebApiSample請在tests/FlexFetcherTests/DependencyInjectionTests/ServiceProviderTests.cs )和samples/WebApiSample.Framework48中查看更多示例。
在我們的示例數據模型中,我們具有嵌套對象:pesuerentity具有地址屬性。讓我們看看如何通過嵌套對象過濾:
var filter = new DataFilter
{
Filters = new List < DataFilter >
{
new ( )
{
Field = "Address.City" , // Address is a nested object, so we use dot notation
Operator = DataFilterOperator . Equal ,
Value = "New York"
}
}
} ;
var flexAddressFilter = new FlexFilter < AddressEntity > ( ) ;
var peopleFilterOptions = new FlexFilterOptions < PeopleEntity > ( ) ;
peopleFilterOptions . AddNestedFlexFilter ( flexAddressFilter ) ;
var flexPeopleFilter = new FlexFilter < PeopleEntity > ( peopleFilterOptions ) ;
var result = flexPeopleFilter . FilterData ( _ctx . People , filter ) . ToList ( ) ;依賴注入可以做同樣的事情:
Services . AddSingleton < FlexFilter < AddressEntity > > ( ) ;
Services . AddSingletonFlexOptions < FlexFilterOptions < PeopleEntity > > ( ( provider , options ) =>
{
options . AddNestedFlexFilter ( provider . GetRequiredService < FlexFilter < AddressEntity > > ( ) ) ;
} ) ;
Services . AddSingleton < FlexFilter < PeopleEntity > > ( ) ;相同的原理可以應用於Flexsorter,FlexPager和FlexFetcher。
在tests/FlexFetcherTests/DependencyInjectionTests/ServiceProviderTests.cs and samples/WebApiSample中查看更多示例。
在以前的示例中,我們僅使用了一個過濾器,但是可以使用或或類似的邏輯使用多個過濾器:
var filter = new DataFilter
{
Logic = DataFilterLogic . Or ,
Filters = new List < DataFilter >
{
new ( )
{
Field = "Name" ,
Operator = DataFilterOperator . Equal ,
Value = "John"
} ,
new ( )
{
Logic = DataFilterLogic . And ,
Filters = new List < DataFilter >
{
new ( )
{
Field = "Name" ,
Operator = DataFilterOperator . Equal ,
Value = "Jane"
} ,
new ( )
{
Field = "Age" ,
Operator = DataFilterOperator . GreaterThan ,
Value = 55
}
}
}
}
} ;FlexFilter以任何深度支撐嵌套過濾器。
如果未指定邏輯,則將設置為默認情況下。
過濾器可以包含(過濾器和邏輯)或(字段,操作員和值)屬性,但不能同時進行。
我們已經看到了具有相同的大型運營商的示例,但是還有更多的運營商可用:
new DataFilter { Field = "Name" , Operator = DataFilterOperator . Equal , Value = "John" } new DataFilter { Field = "Name" , Operator = DataFilterOperator . NotEqual , Value = "John" } new DataFilter { Field = "Age" , Operator = DataFilterOperator . GreaterThan , Value = 55 } new DataFilter { Field = "Age" , Operator = DataFilterOperator . GreaterThanOrEqual , Value = 55 } new DataFilter { Field = "Age" , Operator = DataFilterOperator . LessThan , Value = 55 } new DataFilter { Field = "Age" , Operator = DataFilterOperator . LessThanOrEqual , Value = 55 } new DataFilter { Field = "Name" , Operator = DataFilterOperator . Contains , Value = "Jo" } new DataFilter { Field = "Name" , Operator = DataFilterOperator . StartsWith , Value = "Jo" } new DataFilter { Field = "Name" , Operator = DataFilterOperator . EndsWith , Value = "hn" } new DataFilter { Field = "Age" , Operator = DataFilterOperator . In , Value = new List < int > { 55 , 56 , 57 } } 為了創建自己的過濾器操作員,需要:
BaseFilterExpressionHandler遺傳的自定義filterexpressionHandlerFilterExpressionBuilderAddCustomExpressionHandlers方法看起來像這樣(請參閱tests/FlexFetcherTests/FlexFilterTests/CustomFilterExpressionBuilderTests.cs ):
class CustomExpressionBuilderWithValueTest : FilterExpressionBuilder < PeopleEntity >
{
protected override void AddCustomExpressionHandlers ( List < IFilterExpressionHandler > handlers )
{
handlers . Add ( new ModuleFilterExpressionHandler ( ) ) ;
}
private class ModuleFilterExpressionHandler : BaseFilterExpressionHandler
{
public override string Operator => "MODULE" ;
public override Expression BuildExpression ( Expression property , DataFilter filter )
{
var value = BuildValueExpression ( filter ) ;
return Expression . Equal ( Expression . Modulo ( property , value ) , Expression . Constant ( 0 ) ) ;
}
}
}
var customExpressionBuilder = new CustomExpressionBuilderWithValueTest ( ) ;
var options = new FlexFilterOptions < PeopleEntity > ( customExpressionBuilder ) ;
var flexFilter = new FlexFilter < PeopleEntity > ( options ) ;
var filter = new DataFilter
{
Logic = DataFilterLogic . And ,
Filters = new List < DataFilter >
{
new ( )
{
Field = "Age" ,
Operator = "Module" ,
Value = 15
}
}
} ;
var result = flexFilter . FilterData ( _ctx . People , filter ) . ToList ( ) ;另外,可以創建自定義過濾器操作員,該操作員確實需要值:
class CustomExpressionBuilderWithoutValueTest : FilterExpressionBuilder < PeopleEntity >
{
protected override void AddCustomExpressionHandlers ( List < IFilterExpressionHandler > handlers )
{
handlers . Add ( new EvenNumberFilterExpressionHandler ( ) ) ;
}
private class EvenNumberFilterExpressionHandler : BaseFilterExpressionHandler
{
public override string Operator => "EVEN" ;
public override Expression BuildExpression ( Expression property , DataFilter filter )
{
return Expression . Equal ( Expression . Modulo ( property , Expression . Constant ( 2 , property . Type ) ) , Expression . Constant ( 0 ) ) ;
}
}
}
var customExpressionBuilder = new CustomExpressionBuilderWithoutValueTest ( ) ;
var options = new FlexFilterOptions < PeopleEntity > ( customExpressionBuilder ) ;
var flexFilter = new FlexFilter < PeopleEntity > ( options ) ;
var filter = new DataFilter
{
Logic = DataFilterLogic . And ,
Filters = new List < DataFilter >
{
new ( )
{
Field = "Age" ,
Operator = "Even" ,
Value = null
}
}
} ;
var result = flexFilter . FilterData ( _ctx . People , filter ) . ToList ( ) ;依賴注入的用法可能看起來像這樣(請參閱tests/FlexFetcherTests/DependencyInjectionTests/ServiceProviderTests.cs , GenericFlexFilterWithExpressionBuilderUsage()方法):
class CustomExpressionBuilder : FilterExpressionBuilder < PeopleEntity > ;
class GenericFlexFilterService ( FlexFilter < PeopleEntity > flexFilter )
{
public FlexFilter < PeopleEntity > FlexFilter { get ; } = flexFilter ;
}
var serviceCollection = new ServiceCollection ( ) ;
serviceCollection . AddSingleton < FilterExpressionBuilder < PeopleEntity > , CustomExpressionBuilder > ( ) ;
serviceCollection . AddSingleton < FlexFilterOptions < PeopleEntity > > ( ) ;
serviceCollection . AddSingleton < FlexFilter < PeopleEntity > > ( ) ;
serviceCollection . AddTransient < GenericFlexFilterService > ( ) ;
var serviceProvider = serviceCollection . BuildServiceProvider ( ) ;
var testInstance = serviceProvider . GetRequiredService < GenericFlexFilterService > ( ) ;在這裡, CustomExpressionBuilder是一種自定義過濾器表達式構建器,它傳遞給了FlexFilterOptions構造函數。然後將FlexFilterOptions傳遞給FlexFilter構造函數。最後,將FlexFilter注入了GenericFlexFilterService類。
這似乎有點複雜,但功能非常強大。 Flexfetcher非常靈活。
在以前的示例中,我們使用了字段名稱,就像在實體中一樣,但是可以使用自定義字段名稱。有兩種方法:
最簡單的方法是將字段別名定義為字符串:
// Manual creation of FlexFilter
var addressFilterOptions = new FlexFilterOptions < AddressEntity > ( ) ;
addressFilterOptions . Field ( entity => entity . City ) . Map ( "Town" ) ;
FlexFilter < AddressEntity > addressFilter = new FlexFilter < AddressEntity > ( addressFilterOptions ) ;
// Dependency injection of FlexFetcher
Services . AddSingletonFlexOptions < FlexFetcherOptions < AddressEntity > > ( options =>
{
options . Field ( entity => entity . City ) . Map ( "Town" ) ;
} ) ;
Services . AddSingleton < FlexFetcher < AddressEntity > > ( ) ;在此示例中,我們將“城鎮”田地映射到“城鎮”領域,即我們可以在過濾器和分類器中使用“城鎮”而不是“城市”。
模型類的屬性可以做同樣的事情:
public class AddressModel
{
public string Town { get ; set ; }
}
// Manual creation of FlexFilter
var addressFilterOptions = new FlexFilterOptions < AddressEntity , AddressModel > ( ) ;
addressFilterOptions . Field ( entity => entity . City ) . Map ( model => model . Town ) ;
FlexFilter < AddressEntity , AddressModel > addressFilter = new FlexFilter < AddressEntity , AddressModel > ( addressFilterOptions ) ;
// Dependency injection of FlexFetcher
Services . AddSingletonFlexOptions < FlexFetcherOptions < AddressEntity , AddressModel > > ( options =>
{
options . Field ( entity => entity . City ) . Map ( model => model . Town ) ;
} ) ;
Services . AddSingleton < FlexFetcher < AddressEntity , AddressModel > > ( ) ;在此示例中,我們將equepentity.city屬性映射到advellyModel.town屬性。通常,它可以將視圖模型映射到實體,並為不同的視圖模型具有不同的映射。
允許多個映射,因此可以將一個實體字段映射到多個別名,例如:
options . Field ( entity => entity . City ) . Map ( "Town" ) . Map ( "CityName" ) ;
允許它映射以查看模型屬性和同時串行值:
options . Field ( x => x . City ) . Map ( model => model . Town ) . Map ( "CityName" ) ;
還允許映射到自定義字段(請參見下文):
var customField = new PeopleFullNameCustomField ( ) ; var options = new FlexSorterOptions < PeopleEntity > ( ) ; options . AddCustomField ( customField ) . Map ( "Title" ) ; var flexSorter = new FlexSorter < PeopleEntity > ( options ) ;
在以前的示例中,我們僅使用實體的屬性,但是可以使用具有自定義表達式的自定義字段。
它們可能用於Flexsorter,FlexFilters,FlexFetchers中。
假設我們想將自定義字段添加到peasonentity中:
public class PeopleFullNameCustomField : BaseFlexCustomField < PeopleEntity , string > // string is a type of field
{
public override string Field => "FullName" ;
protected override Expression < Func < PeopleEntity , string > > BuildFieldExpression ( IFlexFetcherContext ? context = null )
{
return p => p . Surname + " " + p . Name ;
}
}
// Manual creation of FlexSorter
var customField = new PeopleFullNameCustomField ( ) ;
var options = new FlexSorterOptions < PeopleEntity > ( ) ;
options . AddCustomField ( customField ) . Map ( "Title" ) ;
var flexSorter = new FlexSorter < PeopleEntity > ( options ) ;
// Dependency injection of FlexFetcher
Services . AddSingletonFlexOptions < FlexFetcherOptions < PeopleEntity > > ( options =>
{
options . AddCustomField ( new PeopleFullNameCustomField ( ) ) . Map ( "Title" ) ; // Map is optional
} ) ;
Services . AddSingleton < FlexFetcher < PeopleEntity > > ( ) ; 在大多數情況下,我們在上一節中看到的自定義字段就足夠了,但是有時需要在過濾器中具有自定義表達式的自定義字段,以進行更複雜的過濾邏輯。
假設我們想將自定義字段“人組”添加到peopleentity,並將“ AnyGroup”過濾器應用於它:
public class PeopleWithManyToManyGroupsCustomFilter : BaseFlexCustomFieldFilter < PeopleEntity >
{
public override string Field => "PeopleGroups" ;
protected override Expression < Func < PeopleEntity , bool > > BuildFilterExpression ( string filterOperator , object ? filterValue ,
IFlexFetcherContext ? context = null )
{
string value = ( string ) filterValue ! ;
return filterOperator switch
{
"AnyGroup" => p => p . PeopleGroups . Any ( pg => pg . Group ! . Name == value ) ,
_ => throw new NotSupportedException ( $ "Invalid filter operator: { filterOperator } " )
} ;
}
}
// Another way to create extended FlexFilter - custom class inherrited from FlexFilter
public class PeopleWithManyToManyGroups : FlexFilter < PeopleEntity >
{
public PeopleWithManyToManyGroups ( PeopleWithManyToManyGroupsCustomFilter customFilter )
{
Options . AddCustomField ( customFilter ) ;
}
}
var customFilter = new PeopleWithManyToManyGroupsCustomFilter ( ) ;
var peopleFilter = new PeopleWithManyToManyGroups ( customFilter ) ; FlexFetcher上下文是一個特殊對象,將傳遞給自定義字段和自定義過濾器。
它可以包含自定義字段和自定義過濾器所需的任何數據。
假設我們需要根據文化選擇不同的實體領域:
public class CustomContext : IFlexFetcherContext // Create your own context class
{
public CultureInfo Culture { get ; set ; } = null ! ;
}
public class PeopleOriginCountryCustomField : BaseFlexCustomField < PeopleEntity , string ? >
{
public override string Field => "Country" ;
protected override Expression < Func < PeopleEntity , string ? > > BuildFieldExpression ( IFlexFetcherContext ? context = null )
{
if ( context is not CustomContext customContext )
{
throw new NotSupportedException ( "Invalid context type" ) ;
}
if ( customContext . Culture . Name == "de-DE" )
{
return entity => entity . OriginCountryDe ;
}
return entity => entity . OriginCountryEn ;
}
}
var customExpressionFilter = new PeopleOriginCountryCustomField ( ) ;
var options = new FlexFilterOptions < PeopleEntity > ( ) ;
options . AddCustomField ( customExpressionFilter ) ;
var flexFilter = new FlexFilter < PeopleEntity > ( options ) ;
var filter = new DataFilter
{
Filters = new List < DataFilter >
{
new ( )
{
Field = "Country" ,
Operator = DataFilterOperator . Equal ,
Value = "Deutschland"
}
}
} ;
var context = new CustomContext
{
Culture = new CultureInfo ( "de-DE" )
} ;
var result = flexFilter . FilterData ( _ctx . People , filter , context ) . ToList ( ) ; 在以前的部分中,我們已經看到瞭如何使用字段以及如何映射它們。默認情況下,所有字段都是可見的,可用於過濾器和分類器。但是在某些情況下,需要隱藏某些字段,以免被用於過濾器和分類器。
有兩種隱藏字段的方法:
將字段定義為隱藏的方式:
var options = new FlexFilterOptions < PeopleEntity > ( ) ;
options . Field ( x => x . CreatedByUserId ) . Hide ( ) ; // CreatedByUserId is a hidden field, it can't be used in filters and sorters
var flexFilter = new FlexFilter < PeopleEntity > ( options ) ;將所有實體字段定義為隱藏的方法:
var options = new FlexFilterOptions < PeopleEntity > ( ) ;
options . HideOriginalFields ( ) ;
var flexFilter = new FlexFilter < PeopleEntity > ( options ) ;場別名不受隱藏的影響,因此即使隱藏了原始場,也可以將它們用於過濾器和分類器。
自定義字段也可能被隱藏:
class SimplePeopleSorterWithCustomSorter : FlexSorter < PeopleEntity >
{
public SimplePeopleSorterWithCustomSorter ( )
{
Options . AddCustomField ( new PeopleFullNameCustomField ( ) ) . Map ( "Title" ) . Hide ( ) ;
}
}當使用hideoriginalfields()時,自定義字段不會自動隱藏,因此應在需要時手動隱藏它們。
FlexFetcher設計用於機器對機器通信,因此能夠序列化和挑選查詢非常重要。
In the simple cases any JSON serializer can be used but as soos as you need to use fields with TimeOnly type or you need to serialize/deserialize arrays to use In operator, you need to apply settings and custom JSON converters from FlexFetcher.Serialization.NewtonsoftJson or FlexFetcher.Serialization.SystemTextJson packages.
安裝FlexFetcher.Serialization.NewtonsoftJson軟件包,並從Helper類獲取設置:
var jsonSettings = NewtonsoftHelper . GetSerializerSettings ( ) ;
var json = JsonConvert . SerializeObject ( filter , jsonSettings ) ;
var deserializedFilter = JsonConvert . DeserializeObject < DataFilter > ( json , jsonSettings ) ;安裝FlexFetcher.Serialization.SystemTextJson軟件包,並從幫助班級獲得設置:
var jsonSettings = SystemTextJsonHelper . GetSerializerOptions ( ) ;
var json = JsonSerializer . Serialize ( filter , jsonSettings ) ;
var deserializedFilter = JsonSerializer . Deserialize < DataFilter > ( json , jsonSettings ) ;還有一些JSON轉換器允許像這樣的簡潔格式序列化/求解對象(dataFilter示例):
{
"L" : " And " ,
"Fs" : [
{
"O" : " Eq " ,
"F" : " Address.Town " ,
"V" : " New York "
}
]
}在tests/FlexFetcherTests/SerializationTests/NewtonsoftTests.cs和Tests/ samples/WebApiSample tests/FlexFetcherTests/SerializationTests/SystemTextJsonTests.cs samples/WebApiSample.Framework48 ,請參見更多簡潔格式的示例。
為了支持簡潔的格式,需要使用FlexFetcher.Serialization.NewtonsoftJson和FlexFetcher.Serialization.SystemTextJson使用下一個轉換器。
FlexFetcherDataSorterConverterFlexFetcherDataSortersConverterFlexFetcherDataPagerConverterFlexFetcherDataFilterConverterFlexFetcherDataQueryConverter所有轉換器都有readOnlyShortForm構造函數參數。如果設置為真,則只允許簡潔的格式進行挑選。否則,將允許完整和簡潔的格式。
通常,在大多數情況下,無需使用readOnlyShortForm ,但是如果您只想將避難所限制為簡潔的格式,則可以將其設置為true。
flexfetcher可以在核心和框架的ASP.NET項目中使用,但是序列化配置不同。
需要下一步以在ASP.NET核心項目中配置序列化(System.Text.json的示例):
FlexFetcherModelBinderFlexFetcherModelBinderProviderAddControllers方法中的設置JSON序列Program.cs設置。 builder . Services . AddControllers ( options =>
{
options . ModelBinderProviders . Insert ( 0 , new FlexFetcherModelBinderProvider ( ) ) ;
} )
. AddJsonOptions ( options =>
{
options . JsonSerializerOptions . Converters . Add ( new GenericConverter ( ) ) ;
// Next converters are optional, but they are needed to support succinct format
options . JsonSerializerOptions . Converters . Add ( new FlexFetcherDataSorterConverter ( ) ) ;
options . JsonSerializerOptions . Converters . Add ( new FlexFetcherDataSortersConverter ( ) ) ;
options . JsonSerializerOptions . Converters . Add ( new FlexFetcherDataPagerConverter ( ) ) ;
options . JsonSerializerOptions . Converters . Add ( new FlexFetcherDataFilterConverter ( ) ) ;
options . JsonSerializerOptions . Converters . Add ( new FlexFetcherDataQueryConverter ( ) ) ;
} ) ;請參閱samples/WebApiSample中的代碼。
需要下一步以在ASP.NET框架項目中配置序列化(newtonsoft.json的示例):
FlexFetcherModelBinderFlexFetcherModelBinderProviderWebApiConfig.cs中的設置JSON序列化設置類似: var jsonSettings = NewtonsoftHelper . GetSerializerSettings ( ) ;
config . Formatters . JsonFormatter . SerializerSettings = jsonSettings ;
// Next converters are optional, but they are needed to support succinct format
config . Formatters . JsonFormatter . SerializerSettings . Converters . Add ( new FlexFetcherDataFilterConverter ( ) ) ;
config . Formatters . JsonFormatter . SerializerSettings . Converters . Add ( new FlexFetcherDataSortersConverter ( ) ) ;
config . Formatters . JsonFormatter . SerializerSettings . Converters . Add ( new FlexFetcherDataSorterConverter ( ) ) ;
config . Formatters . JsonFormatter . SerializerSettings . Converters . Add ( new FlexFetcherDataPagerConverter ( ) ) ;
config . Formatters . JsonFormatter . SerializerSettings . Converters . Add ( new FlexFetcherDataQueryConverter ( ) ) ;
config . Services . Insert ( typeof ( ModelBinderProvider ) , 0 , new FlexFetcherModelBinderProvider ( ) ) ;請參閱samples/WebApiSample.Framework48中的代碼。
存儲庫中有兩個示例項目:
samples/WebApiSample -ASP.NET核心Web API項目samples/WebApiSample.Framework48 ASP.NET框架4.8 Web API項目這兩個項目都具有相同的功能,並演示瞭如何在ASP.NET項目中使用FlexFetcher。
只需構建並運行它們即可查看Flexfetcher在實際項目中的工作方式。使用您喜歡的REST客戶端將請求發送到API。請求的示例可以在samples/WebApiSample/ReadMe.md和samples/WebApiSample.Framework48/ReadMe.md中找到。
另外,在tests/FlexFetcherTests文件夾中還有測試,這些文件夾演示瞭如何在不同方案中使用FlexFetcher。