2015-09-09 2 views
3

Проблема: Я генерирую @Html.ListBoxFor на основе запроса базы данных в моем HttpGet. Во время моей HttpPost я хочу подтвердить, что выбран хотя бы один элемент. Если нет, я просто хочу добавить сообщение проверки.Как сохранить все значения в элементе, выбранном из @ Html.ListBoxFor на веб-странице MVC.net?

Текущий результат: Получаю сообщение «Пожалуйста, выберите хотя бы один элемент», но теперь выбор пуст (элемент выбора есть, но содержит 0 параметров). Я понимаю, что Model.Items будет null в моей HttpPost.

Вопрос: Как использовать мою модель для сохранения Model.Items, чтобы сделать ее не нулевой?

Дополнительная информация: Я стараюсь избегать использования FormCollection collection и дополнительного JavaScript.

--The code--

Контроллер:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     MyViewModel model = new MyViewModel 
     { 
      Items = Enumerable.Range(1, 5).Select(x => new SelectListItem 
      { 
       Value = x.ToString(), 
       Text = "item " + x 
      }) 
     }; 
     return View(model); 
    } 

    [HttpPost] 
    public ActionResult Index(MyViewModel model) 
    { 

     return View(model); 
    } 
} 

Модель:

public class MyViewModel 
{ 
    public MyViewModel() 
    { 
     Items = new List<SelectListItem>(); 
    } 


    [Required(ErrorMessage = "Please select at least one item")] 
    public string[] SelectedItems { get; set; } 

    public IEnumerable<SelectListItem> Items { get; set; } 
} 

Вид:

@model ProjectGenerator.Models.MyViewModel 

@using (Html.BeginForm()) 
{ 
    @Html.ListBoxFor(x => x.SelectedItems, Model.Items) 
    @Html.ValidationMessageFor(x => x.SelectedItems) 
    <button type="submit">OK</button> 
} 
+0

Вам нужно заселить 'SelectList' в методе POST прежде чем вы вернете представление (как и в методе GET). Вы не создаете (не должны) создавать входы для каждого 'SelectListItem', чтобы они не были в данных формы. –

ответ

-1
public IEnumerable<SelectListItem> Items 
    { 
     get 
     {    
      if (HttpContext.Current.Session["MY_ITEMS_TO_LIST_FOR"] == null) 
      { 
       return null; 
      } 
      else 
      { 
       return (IEnumerable<SelectListItem>)HttpContext.Current.Session["MY_ITEMS_TO_LIST_FOR"]; 
      } 
     } 

     set 
     { 
      if (value.Count() > 0) //http post reset value 
      { 
       HttpContext.Current.Session["MY_ITEMS_TO_LIST_FOR"] = value; 
      } 
     } 
    } 

Я протестировал этот путь и работал хорошо. Есть и другие способы, но я нашел это проще. Если вы отлаживаете набор элементов Items items, , вы увидите, что по какой-то причине элементы удаляются из коллекции на странице http, даже если вы используете сеанс. Чтобы предотвратить сбор в сеансе для получения пустой коллекции, я использовал If (Items.Count()> 0). Вы можете увеличить эту идею и настроить свои настройки и настройки.

+0

Будет ли это работать с параллельными вкладками? Например, допустим, что у пользователя две вкладки. В первом списке выбора есть значения {1,2,3}, а второй - {2,3,4}. Затем, если пользователь отправил обратно на тот, который они открыли первым, HttpContext.Current.Session ["MY_ITEMS_TO_LIST_FOR"] был бы написан поверх второй страницы. –

+0

Значения, выбранные пользователем, находятся в переменной SelectedItems, которая не использует Session.Элементы свойств, которые используют сеанс, поступают от сервера к клиенту (только одно направление - используется для заполнения списка), и каждый запрос приносит обновленное значение. Если вы используете Session для переменной, которая будет поступать от клиента, вам нужно использовать идентификатор сеанса, как описано в этом сообщении. http://stackoverflow.com/questions/14373456/how-to-distinguish-session-between-mutiple-tabs-of-browsers – Ferreira

+0

Если вы используете jquery, вы можете создать стандартное действие в своих контроллерах с результатом json и использовать автозаполнение в TemplateView. В программах FIAT также используется для всех списков (поставщиков, пользователей и т. Д.). Но как вы помещаете это не хотите javascript ... – Ferreira

0

Вы не являетесь и не должны создавать элементы управления формой для каждого свойства каждого SelectListItem в собственности Items, чтобы они не были включены в данные формы при отправке. Вам нужно переназначить SelectList в методе POST по возвращении мнение о

public ActionResult Index() 
{ 
    MyViewModel model = new MyViewModel(); 
    ConfigureViewModel(model); 
    return View(model); 
} 

[HttpPost] 
public ActionResult Index(MyViewModel model) 
{ 
    if (!ModelState.IsValid) 
    { 
    ConfigureViewModel(model); 
    return View(model); 
    } 
    // Save and redirect 
} 

private void ConfigureViewModel(MyViewModel model) 
{ 
    model.Items = Enumerable.Range(1, 5).Select(x => new SelectListItem 
    { 
    Value = x.ToString(), 
    Text = "item " + x 
    }); 
} 
-1

один пример, используя JSON результат и templateview. Это хороший образец.

Controller (вы можете настроить JSON, чтобы не допустить ГЭТ):

public class FornecedorController : BaseController 
    { 
     protected FornecedorServices Service = new FornecedorServices(); 

     [HttpGet] 
     [Authorize(Roles = ApplicationRoles.FORNECEDOR_VISUALIZAR)] 
     [OutputCache(NoStore = false, Duration = 3600)] 
     public JsonResult ListarJson(FornecedorParameters parameters) 
     { 
      var model = this.Service.Search(parameters) 
       .Select(x => new 
       { 
        Value = x.Codigo, 
        Description = x.CodigoNomeFantasia 
       }); 
      return this.Json(model, JsonRequestBehavior.AllowGet); 
     } 

    } 

Template View (вы можете настроить свой собственный):

@model int[] 
@{ 
    var id = "id" + Guid.NewGuid().ToString().Substring(0, 5); 
    var disabled = (bool)(this.ViewData["disabled"] ?? false); 
    var showAll = (bool)(this.ViewData["ShowAll"] ?? false); 
    var state = this.ViewData.ModelState[Html.NameFor(x => x).ToString()]; 
    var size = (Size)(this.ViewData["Size"] ?? Size.Big); 
    string css = (state != null && state.Errors.Count > 0) ? "input-validation-error" : string.Empty; 

    List<SelectListItem> listValues; 
    if (this.Model == null) 
    { 
     listValues = new List<SelectListItem>(); 
    } 
    else 
    { 
     listValues = this.Model.Select(x => new SelectListItem { Selected = true, Value = x.ToString(), Text = x.ToString() }).ToList(); 
    } 
} 
<div class="[email protected] @css"> 
    <h3>@Html.LabelFor(model => model):</h3> 
     @Html.ListBox("", listValues, new { id = id }) 
</div> 
<script language="javascript" type="text/javascript"> 
    $("#@id").turnAutoComplete("@Url.Action("ListarJson", "Fornecedor", new { ShowAll = showAll })"@if (showAll) { <text>, checkSelectAll</text> }) 
     .change(function() { 
      @Html.Raw(this.ViewData["OnChange"]) 
     }); 
</script>