Как получить данные из параметров/значений (тегов) Select2 в контроллер в asp.net mvc?

Я пытаюсь использовать Select2 для редактирования тегов для статьи. Моя проблема в том, что поле «Теги» в моей модели представления имеет значение null при возврате в контроллер.

У ArticleTag есть поля Id и Name.

Модель представления

public class EditArticleViewModel
{
    public Guid Id { get; set; }
    public string Header { get; set; }
    public string Description { get; set; }
    [AllowHtml]
    public string Body { get; set; }
    public string Image { get; set; }
    public bool IsPublished { get; set; }
    [UIHint("TagsEditor")]
    public IList<ArticleTag> Tags { get; set; }
}

Вид статьи

<div class="form-group">
@Html.LabelFor(model => model.Tags, new { @class = "control-label col-md-2" })
<div class="col-md-10">
    @Html.EditorFor(model => model.Tags)
    @Html.ValidationMessageFor(model => model.Tags, "", new {@class = "text-danger"})       
</div>

<script type="text/javascript">
    $('#tags')
        .select2({
            data: ["Clare", "Cork", "South Dublin"],
            tags: true,
            tokenSeparators: [','],
            placeholder: "Add your tags here"
        });
</script>

Editor template

@model List<MVCForum.Domain.DomainModel.CMS.ArticleTag>
<select id="tags" multiple="multiple" style="width: 100%">
@for (int i = 0; i < Model.Count; i++)
{       
    <option selected="selected">@Model[i].Name</option>
}
</select>

Теперь я просто не могу понять, как получить данные из моего Editortemplate/View в контроллер. Список имеет значение null при возврате.

Вместо этого я попытался изменить его на список строк (в модели представления, шаблоне редактора и т.д.). Я попытался добавить шаблон редактора для поля «Имя». Тот же результат.

Лучше всего для меня было бы получить теги в виде строки, разделенной запятыми. Но я просто не хочу, чтобы это как-то работало.


person Asger Vestbjerg    schedule 16.08.2016    source источник
comment
Вы не можете привязать <select> к коллекции сложных объектов - вам нужно свойство (скажем) int[] SelectedTags для привязки (при условии, что вы хотите отправить обратно Id выбранных Tags). И замените вас EditorTemplate на @Html.ListBoxFor(m => m.SelectedTags, new SelectList(Model.Tags, "Id", "Name"), а затем $('#SelectedTags').select2() {...   -  person    schedule 17.08.2016
comment
Спасибо за Ваш ответ. Хорошо, поэтому я верну его к списку строк в модели представления и использую @Html.ListBoxFor. Но я не совсем понимаю, что вы имеете в виду, а затем $('#SelectedTags').‌​select2() {....   -  person Asger Vestbjerg    schedule 17.08.2016
comment
<select multiple> возвращает массив простых значений (string, int и т. д.), а не массив сложных объектов. Я не знаю, хотите ли вы привязываться к Id или Name значению ArticleTag, но вашей модели представления требуется массив совпадающих простых значений (string[] или int[]) для привязки. Я предложил назвать его SelectedTags, чтобы id вашего элемента управления было SelectedTags, поэтому он должен быть $('#SelectedTags').‌​select2() {.... И почему вы вручную переопределяете значения, используя data: ....?   -  person    schedule 17.08.2016
comment
Должен ли это быть массив или это может быть список‹строка›? data: это данные автозаполнения, я еще не добрался до этой части.   -  person Asger Vestbjerg    schedule 17.08.2016
comment
Либо List<string>, либо string[]   -  person    schedule 17.08.2016
comment
Итак, теперь у меня есть строка списка в модели представления. Должен ли я использовать @Html.ListBoxFor(m =› m.Tags, new SelectList(Model.Tags), new {@id = tags, @style=width: 100%}) в моем представлении EditArticle? (и пропустить все шаблоны редактора)   -  person Asger Vestbjerg    schedule 17.08.2016
comment
Давайте продолжим обсуждение в чате.   -  person    schedule 17.08.2016


Ответы (1)


<select multiple> возвращает массив простых значений, а не сложных объектов, поэтому вы не можете выполнить привязку к свойству IList<ArticleTag> Tags. Ваша модель представления должна содержать свойство для привязки и свойство для параметров (следующее предполагает, что вы хотите отправить обратно свойство Name каждого выбранного ArticleTag).

public class EditArticleViewModel
{
    public Guid Id { get; set; }
    ....
    [Display(Name = "Tags")]
    public IEnumerable<string> SelectedTags { get; set; }
    public IEnumerable<SelectListItem> TagsList { get; set; }
}

Тогда ваш метод GET будет

var tags = db.ArticleTag.Select(x => x.Name);
var model = new EditArticleViewModel()
{
     TagsList = new SelectList(tags),
     SelectedTags = ... // set values to be selected initially if required
};
return View(model);

Затем удалите свой EditorTemplate и замените его строго типизированным методом ListBoxFor(), чтобы он привязывался к свойствам вашей модели.

@Html.ListBoxFor(m => m.SelectedTags, Model.TagsList)

и измените скрипт, чтобы он использовал атрибут id, сгенерированный методом ListBoxFor().

$('#SelectedTags').select2({
    tags: true,
    tokenSeparators: [','],
    placeholder: "Add your tags here"
});
person Community    schedule 17.08.2016
comment
Привет, Стивен, ты знаешь, как я могу реализовать это, когда теги исходят из списка объектов с двумя строковыми свойствами? 1 для отображаемого имени и 1 для значения? - person Bassie; 08.03.2018
comment
@Bassie, не уверен, что понимаю - вы хотите отобразить (скажем) свойство Name ваших объектов, но отправить обратно связанные Id выбранных объектов? - person ; 08.03.2018
comment
Я действительно нашел решение для этого. Я искал следующее: @Html.ListBoxFor(m => m.SelectedTags, new SelectList(users, "UserName", "DisplayName")) поэтому теги используют свойство DisplayName для отображения пользователя, но строковые значения, которые отправляются, поступают из свойства UserName - person Bassie; 08.03.2018
comment
@Bassie - В качестве примечания, рекомендуется, чтобы свойство users было IEnumerable<SelectListItem>, а не IEnumerable<yourObject>), поэтому в представлении это просто @Html.ListBoxFor(m => m.SelectedTags, users) - person ; 08.03.2018