我遇到的情況,我有一定的基類,我們將其稱之爲「PagingCriteriaBase」自定義模型綁定在Asp.Net核心的子類
public class PagingCriteriaBase : CriteriaBase
{
public Int32 CountOfItemsPerPage { get; set; }
public SortOrder SortingOrder { get; set; }
public String SortBy { get; set; }
public Int32 PageNo { get; set; }
public PagingCriteriaBase(Int32 pageNo,Int32 countOfItemsPerPage, SortOrder sortingOrder, String sortBy,Int32 draw)
{
this.PageNo = pageNo>0?pageNo:1;
this.CountOfItemsPerPage = countOfItemsPerPage>0?countOfItemsPerPage:10;
this.SortBy = sortBy;
this.SortingOrder = sortingOrder;
this.Draw = draw;
}
}
,然後我有其他類將繼承「 PagingCriteriaBase」,例如
public class UserCriteria:PagingCriteriaBase
{
public String Email { get; set; }
public String DisplayName { get; set; }
public UserCriteria():base(1,0,SortOrder.Asc,"",1)
{
}
public UserCriteria(Int32 pageNo,Int32 countOfItemsPerPage, SortOrder sortingOrder, String sortBy, Int32 draw)
:base(pageNo, countOfItemsPerPage,sortingOrder,sortBy,draw)
{
}
}
現在我想要做的是什麼,我想創建一個模型綁定,將與網頁API方法一起使用,並且模型粘結劑將與所有的子類中使用「PagingCriteriaBase」,這個模型綁定的目的是根據t來設置一些屬性O數據從Ajax請求的到來,我想做到以下幾點:
我創建瞭如下一個實現 「IModelBinder」 一類:
public class PagingModelBinder : IModelBinder { public Task BindModelAsync(ModelBindingContext bindingContext) { if (!bindingContext.ModelType.IsSubclassOf(typeof(PagingCriteriaBase))) { return Task.FromResult(false); } String startModelName = "start"; String lengthModelName = "length"; var startResult = bindingContext.ValueProvider.GetValue(startModelName); var lengthResult = bindingContext.ValueProvider.GetValue(lengthModelName); Int32 start, length; if (!Int32.TryParse(startResult.FirstValue, out start)) { start = 0; } if (!Int32.TryParse(lengthResult.FirstValue, out length)) { length = SystemProp.PAGE_SIZE; } else { length = 20; } var model = Activator.CreateInstance(bindingContext.ModelType); Int32 pageNo = (int)Math.Ceiling((decimal)start/length); bindingContext.ModelState.SetModelValue("PageNo", new ValueProviderResult(pageNo.ToString())); bindingContext.ModelState.SetModelValue("CountOfItemsPerPage", new ValueProviderResult(length.ToString())); bindingContext.Model = model; var mProv = (IModelMetadataProvider)bindingContext.HttpContext.RequestServices.GetService(typeof(IModelMetadataProvider)); bindingContext.Result = ModelBindingResult.Success(model); return Task.CompletedTask; } }
我創建了一個ModelBinderProvider如下:
public class PagingEntityBinderProvider:IModelBinderProvider { public IModelBinder GetBinder(ModelBinderProviderContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.Metadata.ModelType == typeof(PagingCriteriaBase)) { return new BinderTypeModelBinder(typeof(PagingModelBinder)); } return null; } }
我註冊使用模型綁定:
services.AddMvc(op => op.ModelBinderProviders.Insert(0, new PagingEntityBinderProvider())) ;
在我的Web API方法,我做了以下內容:
public IActionResult GetAll([ModelBinder(typeof(PagingModelBinder))]UserCriteria crit) { //Code goes here }
當我使用的模型粘合劑如上面我發現,一旦代碼到達的Web API的方法,從數值沒什麼例如「PageNo」屬性保持爲1,所以我需要做的是讓模型聯編程序設置子類對象的所有相關屬性,而不管類本身的類型如何,最後一次代碼到達Web API方法,模型將會正確設置所有屬性,請問我需要在代碼中更改哪些內容以處理此問題?
請注意,我使用Asp.Net核2.0
感謝@laksmono,首先,「PropertyInfo」的SetValue方法給了我一個錯誤,因爲String和Int32之間的類型不同,但我將代碼更改爲:012.SXValue(model,Convert.ChangeType(v .RawValue,pi.PropertyType)) 並按預期工作。 –