未能绑定字符串索引的查询字符串参数

时间:2019-05-03 21:26:49

标签: c# asp.net-core asp.net-core-mvc model-binding

我正在尝试绑定一些由字符串键索引的查询字符串参数,但是我似乎无法使其工作

这是我尝试绑定的值

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; }
}

除搜索类对象外,其余模型均已正确绑定,我对请求中包含该对象的值进行了三倍检查,我在这里遗漏了什么? ps。相同的代码据说可以在.net核心之前运行

3 个答案:

答案 0 :(得分:3)

更多的代码背景将对您有所帮助,例如实际上正在执行绑定的代码部分,但这是一个带查询参数绑定的dotnetcore控制器示例。在C#中,类名和字段都是大写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; }
    }
}

答案 1 :(得分:0)

似乎没有人对此有一个答案,所以我走了一条不同的路线,写了我自己的自定义活页夹,如果有更好的答案,我会接受它而不是这个,那么以后可能会重构它(哈哈哈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;
    }
}

答案 2 :(得分:0)

  1. 您不需要手动绑定每个字段。使用反射将使其变得容易。
  2. Aslo,不需要手动绑定那些外部模型的属性(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;
    }
}

然后用search装饰[ModelBinder(typeof(QueryStringDictSyntaxBinder<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&
相关问题