0

根据标题,我在 HTML5 页面上使用最新的 select2 选择框,并使用他们的示例调用我创建的 Web API 2 端点。

出于测试目的,端点只需构建标签集合并将结果作为 HttpResponseMessage 返回。这是一些可视化的代码:

标签实体

public class TagData
{
    public string Id { get; set; }
    public string Text { get; set; }
}

该模型:

public class TagsModel
{
    public IEnumerable<TagData> Tags { get; set; }
}

Web API 2 项目中的控制器操作:

    public IHttpActionResult Get()
    {
        var tags = new TagsModel()
        {
            Tags = new List<TagData>
            {
                new TagData()
                {
                    Id = "1",
                    Text = "Tag1"
                },
                new TagData()
                {
                    Id = "2",
                    Text = "Tag2"
                }
            }
        };
        return Ok(tags);
    }

我敲了一个单元测试,它也可以使用 composer 在 Fiddler4 中运行一个测试,返回以下 JSON 响应:

{"Tags":[{"Id":"1","Text":"Tag1"},{"Id":"2","Text":"Tag2"},{"Id":"3","Text":"Tag3"}}]}

在 HTML5 页面中,我放入了标准的 select2 html 元素:

    <select class='s2-search-box form-control' multiple='multiple'></select>

这里的想法是将 select2 控件绑定到远程数据,然后使用标记功能允许用户找到一个标记,选择它并重复,所以这是使用这个 ajax 调用完成的:

    $(document).ready(function () {

        $(".s2-search-box").select2({
            ajax: {
                url: "http://localhost:54850/api/s2demo",
                dataType: 'json',
                delay: 250,
                data: function (params) {
                    return {
                        q: params.term, // search term
                        page: params.page
                    };
                },
                processResults: function (data, page) {
                    // parse the results into the format expected by Select2.
                    // since we are using custom formatting functions we do not need to
                    // alter the remote JSON data
                    return {
                        results: data.Tags
                    };
                },
                cache: true
            }
        });
    });

到目前为止一切顺利,我的单元测试工作正常,当我使用 Firebug 检查 ajax 调用时,我可以看到数据以正确的格式返回,并且我能够显示 data.Tags 集合,所以我知道数据在那里但是实际select2 下拉菜单显示“未定义”项目的列表,实际上并没有显示我想要的数据或允许我从这些选择中创建标签。

作为旁注,我也尝试了这个:

    $(".s2-search-box").select2({
        ajax: {
            url: "http://localhost:54850/api/s2demo",
            dataType: "json",
            type: "GET",
            data: function (params) {

                var queryParameters = {
                    term: params.term
                }
                return queryParameters;
            },
            processResults: function (data) {
                return {
                    results: $.map(data, function (item) {
                        return {
                            text: item.Text,
                            id: item.Id
                        }
                    }),
                    pagination: {
                        more: data.more
                    }
                };
            }
        }
    });

这样做的原因是我可以创建标签,以便它们在 select2 控件中显示为:

标签1[x] 标签2[x]

但是下拉列表会永久显示。

我正在使用最新的 4.0.2 版本的 select2 库。

提前致谢。

4

1 回答 1

3

在花费了几个小时后终于解决了这个问题,主要是因为信息分散,而且新版本的 select2 现在没有被广泛使用。

所以我必须先对控制器进行一些更改,以允许我发出 GET 和 POST 请求(有更好的方法可以做到这一点,但为了原型制作这个工作):

    [AcceptVerbs("GET","POST")]
    public IHttpActionResult TagLookup([FromBody]string value)
    {
        var tags = TagsModel;

        var results = new TagsModel();
        var tagsList = new List<TagData>();
        var i = 0;

        foreach (var m in tags.Tags)
        {
            i++;
            if (m.Text.Contains(value))
            {
                tagsList.Add(new TagData()
                {
                    Id = i.ToString(),
                    Text = m.Text
                });
            }
        }

        results.Tags = tagsList;

        return Ok(results);
    }

代码块很简单,我返回一个包含标签集合(TagaData 实体)的模型,但不同的是操作上的装饰器,AcceptVerbs 属性接受来自任何客户端的 GET 和 POST 请求。

我还添加了 [FromBody] 参数属性,它强制 Web API 从请求正文中读取简单类型(对于复杂类型,您将使用 FromUri)。

然后我修改了 HTML 页面中的 Ajax 调用,如下所示:

    $(document).ready(function () {

        $(".s2-search-box").select2({
            ajax: {
                url: "http://localhost:54850/api/s2demo",
                contentType: "application/x-www-form-urlencoded; charset=UTF-8",
                type: 'POST',
                dataType: 'json',
                delay: 250,
                data: function(params) {
                    return '=' + params.term; // search term
                },
                processResults: function(data) {
                    return {
                        results: $.map(data.Tags, function(item) {
                            return {
                                text: item.Text,
                                id: item.Id
                            }
                        })
                    };
                },
                cache: true
            }
        });
    });

因此,这里需要注意的重要一点是,该函数将参数传递给正在发送的数据有效负载,但这里 Web API 2 的问题是我必须在返回值上加上“=”符号:

return '=' + params.term; 

这是必需的,以便 Web API 了解如何处理该参数,否则它会被忽略。

“processResults:”部分标记了 Tags 数组并将数据绑定到 select2 控件,为我提供了一个填充的下拉列表(如果返回的任何数据与传入的术语匹配)。

现在我也可以选择一个标签,它将作为输入框中的标签出现在 select2 中,我通过确保在 select2 html 控件中包含多个属性来做到这一点:

<select class="s2-search-box form-control" multiple="multiple"></select>

这对我来说已经分类了,希望能为其他挠头的人提供一些启示。在下一部分,获取 select2 框中的标签并将它们发送到另一个 Web API 控制器操作。

于 2016-05-21T05:16:47.030 回答