#asp.net #asp.net-mvc
#asp.net #asp.net-mvc
Вопрос:
Я создаю простую страницу поиска в MVC с некоторыми фильтрами. Фильтры представлены свойствами в моей ViewModel. Моя ViewModel привязана к форме GET в cshtml, поэтому мой фильтр появится в строках запросов, и пользователь сможет добавить в закладки свой поиск.
Что я хочу сделать, так это присвоить значение по умолчанию некоторым из моих фильтров.
Моя (упрощенная) ViewModel :
public class SearchViewModel
{
//Filter I want to set a default value to
public OrganizationType? OrganizationType {get; set;}
//Results of the search
public IEnumerable<ItemViewModel> Items {get; set;}
}
Я хотел бы установить значение по умолчанию для OrganizationType. Я не могу просто установить его в конструкторе SearchViewModel, потому что это зависит от текущего пользователя :
public void InitViewModel(SearchViewModel vm)
{
vm.OrganizationType = _someLogic.GetDefaultValue(_currentUser);
}
Первым решением было просто проверить, имеет ли значение OrganizationType значение null, а затем присвоить значение по умолчанию :
public ActionResult Search(SearchViewModel vm)
{
if(vm.OrganizationType == null)
vm.OrganizationType = _someLogic.GetDefaultValue(_currentUser);
return View(vm);
}
Но это решение не работает, поскольку нулевое значение соответствует пустому фильтру, и это выбор, который может сделать пользователь. Поэтому я не могу его переопределить.
Второе решение, которое я попробовал, состояло в том, чтобы указать, что значение по умолчанию контроллера должно быть null в действии поиска :
public ActionResult Search(SearchViewModel vm = null)
{
if (vm == null)
{
vm = new SearchViewModel();
InitViewModel(vm);
}
...
return View(vm);
}
Но на практике переменная vm никогда не имеет значения null, поэтому значения по умолчанию никогда не устанавливаются.
Я также попытался выполнить два действия, одно без ViewModel, где я создаю экземпляр новой ViewModel со значениями по умолчанию, а затем вызываю второе действие :
public ActionResult Search()
{
var vm = new SearchViewModel();
InitViewModel(vm);
//Simply call the second action with the initizalied ViewModel
return Search(vm);
}
public ActionResult Search(SearchViewModel vm)
{
...
return View(vm);
}
Но это не работает, потому что теперь существует двусмысленность между двумя действиями, и asp.net не знает, какой из них выбрать.
Итак, вкратце, я хотел бы найти способ установить значение по умолчанию для ViewModel, не устанавливая его в конструкторе и не переопределяя выбор пользователя.
Другой способ сказать это, как я могу отличить «пустую» ViewModel от той, где некоторые значения привязаны к форме.
Есть идеи?
Комментарии:
1. Почему вы не можете использовать
_currentUser
?2. @markpsmith, _currentUser является переменной-членом моего контроллера, которая зависит от текущего HttpContext. Я могу использовать его в своем контроллере, но я не могу использовать его в конструкторе ViewModel, поскольку у меня нет чистого способа доступа к HttpContext оттуда.
3. Предполагая, что вы используете MVC5 и C # 5, можете ли вы попробовать это? тип общественной организации? OrganizationType {get; set;} = null; // или любое другое значение, которое вы хотите установить по умолчанию
4. @PratikGaikwad проблема в том, что я не могу легко установить значение по умолчанию для OrganizationType , для этого мне нужен текущий пользователь, а затем я делаю запрос к своей базе данных, чтобы получить тип организации по умолчанию для текущего пользователя (который может быть нулевым).
5. Является
OrganizationType
ли перечисление? Если вы можете его изменить, почему бы вам не добавитьNone
значение, скажем,-1
которое представляло бы значение, которое отправляется, когда пользователь не делает выбор. Итак, при первой загрузке вашей страницы вы можете проверить, имеет лиOrganizationType
значение null, а затем установить его по умолчанию. В противном случаеNone
означает отсутствие выбора.
Ответ №1:
Хорошо, я думаю, что нашел решение своей собственной проблемы…
Я могу использовать свойство ModelState контроллера, чтобы проверить, является ли ViewModel пустым или был привязан из формы :
public ActionResult Search(SearchViewModel vm = null)
{
if (ModelState.Count == 0)
{
InitViewModel(vm);
}
...
return View(vm);
}
Так что, если ModelState.Значение Count равно 0, это означает, что пользователь не менял никаких фильтров. Таким образом, форма пуста, и мы можем привязать наши значения по умолчанию. Как только пользователь изменит один из фильтров или отправит запрос, ModelState.Количество будет больше 0, поэтому мы не должны устанавливать значение по умолчанию. В противном случае мы бы переопределили выбор пользователя.
Ответ №2:
Логика того, что вы делаете, немного сомнительна. Вообще говоря, если значение имеет значение null, то null является значением по умолчанию. Однако, похоже, что вы пытаетесь провести здесь различие между тем, является ли значение null, потому что оно не установлено, или null, потому что пользователь явно установил для него значение null. Этот тип семантической дисперсии обычно является плохой идеей. Если значение null имеет значение, то оно всегда должно иметь это значение. В противном случае ваш код становится более запутанным, и в результате обычно появляются ошибки.
Тем не менее, вы не можете рассчитывать на ModelState
отсутствие элементов. Я, честно говоря, никогда не играл с ModelState
достаточным количеством в сценариях, где нет данных post, но, возможно, есть какой-то сценарий, в котором нет данных post и все же ModelState
могут быть элементы. Даже если его нет, это деталь реализации. Что делать, если Microsoft выполняет обновление, которое добавляет элементы ModelState
в ситуации, в которых их ранее не было. Затем ваш код прерывается без видимой причины.
Единственное, на что вы действительно можете рассчитывать здесь, является ли метод запроса GET или POST . В версии GET вашего действия вы можете разумно предположить, что пользователь не внес никаких изменений. Поэтому в этом сценарии вы можете просто установить значение на любое, которое вам нравится, не беспокоясь.
В версии POST вашего действия пользователь внес какие-то изменения. Однако на данный момент больше невозможно определить, является ли значение null, потому что оно есть, или потому, что пользователь явно хотел, чтобы оно было. Поэтому вы должны учитывать значение как есть.
Комментарии:
1. Я согласен, что проводить различие между «значением null по умолчанию» и значением null, установленным пользователем, не самая лучшая идея. Но я хочу, чтобы моя инициализация ViewModel была простой и возможной. Установка значения по умолчанию для некоторых пользователей является частным случаем, а не общепринятым. Меня интересует только запрос GET, запрос поступает из HTML-формы, поэтому пользователь, вероятно, внес изменения.