无法绑定字符串索引查询字符串参数
failing to bind string indexed query string parameters
我正在尝试绑定一些由字符串键索引的查询字符串参数,但我似乎无法让它工作
这是我试图绑定的值
search[value]: Exception happ...
search[regex]: false
这是我要绑定的模型
getLogsAjax(DataTableAjaxPostModel model)
public class DataTableAjaxPostModel
{
public int draw { get; set; }
public int start { get; set; }
public int length { get; set; }
public List<Column> columns { get; set; }
public search search { get; set; }
public List<Order> order { get; set; }
}
public class search
{
public string value { get; set; }
public string regex { get; set; }
}
除搜索 class 对象外,模型的其余部分已正确绑定,我三次检查请求是否包含该对象的值,我在这里缺少什么?
p.s。据说相同的代码在 .net 核心之前工作
代码的更多背景知识会有所帮助,例如实际执行绑定的代码部分,但这里是一个带有查询参数绑定的 dotnetcore 控制器示例。 C# 中的常见做法是 class 名称和字段均为大写 FYI。
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
public class SampleController : Controller
{
[HttpGet]
[Route("")]
public IActionResult ExampleGet([FromQuery] DataTableAjaxPostModel dataTableAjaxPostModel)
{
// You should be able to debug and see the value here
var result = dataTableAjaxPostModel.search;
return Ok();
}
public class DataTableAjaxPostModel
{
public int draw { get; set; }
public int start { get; set; }
public int length { get; set; }
public List<Column> columns { get; set; }
public search search { get; set; }
public List<Order> order { get; set; }
}
public class search
{
public string value { get; set; }
public string regex { get; set; }
}
}
似乎没有人对此有答案,所以我采取了不同的路线并编写了我自己的自定义活页夹,如果有更好的答案出现,我会接受它而不是这个,以后可能会重构它(哈哈哈 IKR !)
public class DTModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
try
{
var result = new DataTableAjaxPostModel();
if (bindingContext.HttpContext.Request.Query.Keys.Contains("draw"))
result.draw = int.Parse(bindingContext.ValueProvider.GetValue("draw").FirstValue);
if (bindingContext.HttpContext.Request.Query.Keys.Contains("search[value]") &&
bindingContext.HttpContext.Request.Query.Keys.Contains("search[regex]"))
result.search = new search()
{
regex = bindingContext.ValueProvider.GetValue("search[regex]").FirstValue,
value = bindingContext.ValueProvider.GetValue("search[value]").FirstValue
};
//...
bindingContext.Result = ModelBindingResult.Success(result);
}
catch
{
bindingContext.Result = ModelBindingResult.Failed();
}
return Task.CompletedTask;
}
}
- 您不需要手动绑定每个字段。使用反射会很容易。
- 此外,无需手动绑定那些外部模型的属性(
DataTableAjaxPostModel
的属性)。那是因为它们将由 内置 模型绑定器完成。
实施
创建自定义活页夹 QueryStringDictSyntaxBinder<TModel>
:
internal class QueryStringDictSyntaxBinder<TModel> : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
try
{
var result = Activator.CreateInstance<TModel>();
foreach(var pi in typeof(TModel).GetProperties())
{
var modelName = bindingContext.ModelName;
var qsFieldName = $"{modelName}[{pi.Name}]";
var field= bindingContext.HttpContext.Request.Query[qsFieldName].FirstOrDefault();
if(field != null){
pi.SetValue(result,field);
}
// do nothing if null , or add model binding failure messages if you like
}
bindingContext.Result = ModelBindingResult.Success(result);
}
catch
{
bindingContext.Result = ModelBindingResult.Failed();
}
return Task.CompletedTask;
}
}
然后用 [ModelBinder(typeof(QueryStringDictSyntaxBinder<search>))]
装饰 search
属性 :
public class DataTableAjaxPostModel
{
public int draw { get; set; }
public int start { get; set; }
public int length { get; set; }
public List columns { get; set; }
[ModelBinder(typeof(QueryStringDictSyntaxBinder<search>))]
public search search { get; set; }
public List order { get; set; }
}
测试用例:
我用以下请求对其进行了测试,它对我来说工作正常:
?draw=1&search[value]=abc&search[regex]=(.*)&
?draw=1&sEarCh[value]=opq&Search[regex]=([^123]*)&
?draw=1&seaRch[value]=rst&Search[regex]=(.*)&
?draw=1&Search[value]=abc&
?draw=1&
我正在尝试绑定一些由字符串键索引的查询字符串参数,但我似乎无法让它工作
这是我试图绑定的值
search[value]: Exception happ...
search[regex]: false
这是我要绑定的模型
getLogsAjax(DataTableAjaxPostModel model)
public class DataTableAjaxPostModel
{
public int draw { get; set; }
public int start { get; set; }
public int length { get; set; }
public List<Column> columns { get; set; }
public search search { get; set; }
public List<Order> order { get; set; }
}
public class search
{
public string value { get; set; }
public string regex { get; set; }
}
除搜索 class 对象外,模型的其余部分已正确绑定,我三次检查请求是否包含该对象的值,我在这里缺少什么? p.s。据说相同的代码在 .net 核心之前工作
代码的更多背景知识会有所帮助,例如实际执行绑定的代码部分,但这里是一个带有查询参数绑定的 dotnetcore 控制器示例。 C# 中的常见做法是 class 名称和字段均为大写 FYI。
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
public class SampleController : Controller
{
[HttpGet]
[Route("")]
public IActionResult ExampleGet([FromQuery] DataTableAjaxPostModel dataTableAjaxPostModel)
{
// You should be able to debug and see the value here
var result = dataTableAjaxPostModel.search;
return Ok();
}
public class DataTableAjaxPostModel
{
public int draw { get; set; }
public int start { get; set; }
public int length { get; set; }
public List<Column> columns { get; set; }
public search search { get; set; }
public List<Order> order { get; set; }
}
public class search
{
public string value { get; set; }
public string regex { get; set; }
}
}
似乎没有人对此有答案,所以我采取了不同的路线并编写了我自己的自定义活页夹,如果有更好的答案出现,我会接受它而不是这个,以后可能会重构它(哈哈哈 IKR !)
public class DTModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
try
{
var result = new DataTableAjaxPostModel();
if (bindingContext.HttpContext.Request.Query.Keys.Contains("draw"))
result.draw = int.Parse(bindingContext.ValueProvider.GetValue("draw").FirstValue);
if (bindingContext.HttpContext.Request.Query.Keys.Contains("search[value]") &&
bindingContext.HttpContext.Request.Query.Keys.Contains("search[regex]"))
result.search = new search()
{
regex = bindingContext.ValueProvider.GetValue("search[regex]").FirstValue,
value = bindingContext.ValueProvider.GetValue("search[value]").FirstValue
};
//...
bindingContext.Result = ModelBindingResult.Success(result);
}
catch
{
bindingContext.Result = ModelBindingResult.Failed();
}
return Task.CompletedTask;
}
}
- 您不需要手动绑定每个字段。使用反射会很容易。
- 此外,无需手动绑定那些外部模型的属性(
DataTableAjaxPostModel
的属性)。那是因为它们将由 内置 模型绑定器完成。
实施
创建自定义活页夹 QueryStringDictSyntaxBinder<TModel>
:
internal class QueryStringDictSyntaxBinder<TModel> : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
try
{
var result = Activator.CreateInstance<TModel>();
foreach(var pi in typeof(TModel).GetProperties())
{
var modelName = bindingContext.ModelName;
var qsFieldName = $"{modelName}[{pi.Name}]";
var field= bindingContext.HttpContext.Request.Query[qsFieldName].FirstOrDefault();
if(field != null){
pi.SetValue(result,field);
}
// do nothing if null , or add model binding failure messages if you like
}
bindingContext.Result = ModelBindingResult.Success(result);
}
catch
{
bindingContext.Result = ModelBindingResult.Failed();
}
return Task.CompletedTask;
}
}
然后用 [ModelBinder(typeof(QueryStringDictSyntaxBinder<search>))]
装饰 search
属性 :
public class DataTableAjaxPostModel { public int draw { get; set; } public int start { get; set; } public int length { get; set; } public List columns { get; set; } [ModelBinder(typeof(QueryStringDictSyntaxBinder<search>))] public search search { get; set; } public List order { get; set; } }
测试用例:
我用以下请求对其进行了测试,它对我来说工作正常:
?draw=1&search[value]=abc&search[regex]=(.*)&
?draw=1&sEarCh[value]=opq&Search[regex]=([^123]*)&
?draw=1&seaRch[value]=rst&Search[regex]=(.*)&
?draw=1&Search[value]=abc&
?draw=1&