Это моя модель:
public class IndexViewModel
{
public FilterConditions conditions { get; set }
public IEnumerable<SelectListItem> Countries { get; set }
}
public class FilterConditions
{
public string condition11 { get; set }
// ...
}
И у меня есть метод действия Index
, например:
public ActionResult Index()
{
var model = new IndexViewModel();
// fill the model here with default values
return View(model);
}
Вид отображает форму с условиями фильтра в качестве входных типов.
Теперь я хочу, чтобы сообщение назад из этой формы обрабатывалось с помощью этого метода действий:
[HttpPost]
public ActionResult Index(FilterConditions model)
{
// do some magic with model and return another view here
}
и это действительно работает (я ставлю точку останова в методе и вызывается), но свойства моей модели всегда пусты (значения по умолчанию), в то время как они должны содержать значения, которые были отправлены формой.
Когда я изменяю метод действия следующим образом:
[HttpPost]
public ActionResult Index(IndexViewModel model)
{
// do some magic with model.conditions and return another view here
}
Все работает так, как должно, но это не "правильно" (IMHO), так как мне не нужен список "Страны" по возвращении, мне нужна только выбранная страна (что является одним из условий).
Что такое хороший (лучший способ), чтобы сделать эту работу без необходимости использовать всю исходную модель представления в качестве входного параметра?
Btw, я использую ASP.NET MVC 2 (я не думаю, что это действительно имеет значение, так как я думаю, что та же проблема в MVC 3, но я не совсем уверен в этом).
(Я искал в Интернете "лучшие практики" в отношении dropdownlists и viewmodels в asp.net mvc, но разные рекомендации, которые я нашел, на самом деле не совпадали друг с другом, и многое уже устарело Я не нашел "официальную" наилучшую практику вокруг этого. Надеюсь, я пойду в правильном направлении (имея список как часть моей модели просмотра), не стесняйтесь исправлять меня по этому вопросу, если я не буду. Также не стесняйтесь указывать мне "одобренные лучшие практики" об этом, если вы знаете о них.)
Обновить:
Я узнал, что могу использовать атрибут [Bind] с префиксом "условий фильтрации". И это действительно работает для этой точки зрения. Но моя оригинальная проблема (я признаю, что она не была включена в мой вопрос) не решена.
Бывает так, что этот конкретный метод действий также вызывается из другого представления (это вызов ajax), где он не имеет этого префикса, и в этом случае он больше не работает. Любые предложения?
Я нашел решение.
По-видимому, когда я использую одно имя для переменной параметра как имя типа (случай не должен совпадать), например:
[HttpPost]
public ActionResult Index(FilterConditions filterConditions)
{
// do some magic with model and return another view here
// now the filterConditions variable actually contains values!
}
Все работает так, как должно (значения моих фильтровConditions больше не пусты /null ). По-видимому, по умолчанию modelbinder использует имя параметра в качестве потенциального префикса для привязки.
Я рад, что узнал, но было бы неплохо, если бы это было где-то более четко документировано. Это не очевидно.
Edit: По запросу: это код на мой взгляд (aspx):
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyProject.Models.IndexViewModel>" %>
<%-- ... more stuff here ... --%>
<% using (Html.BeginForm())
{%>
<%= Html.ValidationSummary(true)%>
<fieldset>
<div class="editor-label">
<%= Html.LabelFor(model => model.FilterConditions.Country)%>
</div>
<div class="editor-field">
<%= Html.DropDownListFor(model => model.FilterConditions.Country, Model.Countries)%>
<%= Html.ValidationMessageFor(model => model.FilterConditions.Country)%>
</div>
<div class="editor-label">
<%= Html.LabelFor(model => model.FilterConditions.Make)%>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(model => model.FilterConditions.Make)%>
<%= Html.ValidationMessageFor(model => model.FilterConditions.Make)%>
</div>
<%-- ... more fields inserted here ... --%>
<p>
<input type="submit" value=" Search... " />
</p>
</fieldset>
<% } %>
Привет, fretje: Теперь я могу использовать ваш способ решить вашу проблему. Сначала у меня есть две модели "IndexViewModel" и "Index", а DropDownList (неважно, просто предлагайте элементы DropDown):
public class IndexViewModel : Index
{
//public int value { get; set; }
public List<System.Web.Mvc.SelectListItem> items { get; set; }
}
public class Index
{
public int value { get; set; }
}
class DropDownList
{
public List<System.Web.Mvc.SelectListItem> GetDropDownList()
{
List<System.Web.Mvc.SelectListItem> result = new List<System.Web.Mvc.SelectListItem>();
result.Add(new System.Web.Mvc.SelectListItem
{
Value = "1",
Text = "Apple"
});
result.Add(new System.Web.Mvc.SelectListItem
{
Value = "2",
Text = "Milk"
});
return result;
}
}
И два контроллера - Test() и Test (Models.Index), я передаю IndexViewModel и postback IndexModel:
public ActionResult Test()
{
var result =
new Models.IndexViewModel
{
value = 1,
items = new Models.DropDownList().GetDropDownList()
};
return View(result);
}
[HttpPost]
public ActionResult Test(Models.Index posatback)
{
return View();
}
Вид теста():
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-field">
<%: Html.DropDownListFor(m=>m.value, Model.items )%>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
которые работают! спасибо, я узнал еще одну технику.:)
Возможно, вы можете попробовать
[HttpPost]
public ActionResult Index([Bind(Exclude="Countries")]IndexViewModel model)
{
// do some magic with model.conditions and return another view here
}
Привет ~ Вам не нужно комбинировать весь SelectListItem с ViewModel, на самом деле ваш ViewModel имеет только поле для хранения выбора пользователя, целого или строкового, а затем использовать DropDownListFor, например:
<%: Html.DropDownListFor(item.WeaponID, MyApplication.Models.DropDownList.GetDropDownList() )%>
см. мой пост в моем блоге, я использую очень простой пример, чтобы объяснить: http://maidot.blogspot.com/2011/04/aspnet-mvc-viewdropdownlistfor.html
сообщите мне, если у вас есть проблемы:)