2016-10-18 5 views
0

Я делаю простой Поиск в странице в MVC с некоторыми фильтрами в нем. Фильтры представлены свойствами в моей модели ViewModel. My ViewModel привязан к форме GET в cshtml, поэтому мой фильтр появится в querystrings, и пользователь сможет добавить в закладки свой поиск.Значение по умолчанию для ViewModel

Что я хочу сделать, это присвоить значение по умолчанию некоторым из моих фильтров.

My (упрощенный) 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 имеет нулевое значение, а затем присвоить значение по умолчанию:

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 никогда не является нулевым, поэтому по умолчанию значения никогда не устанавливаются.

Я также попробовал наличие двух действий, один заменяется без модели представления, где я новый создания экземпляра 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 от той, где некоторые значения привязаны к форме.

Есть идеи?

+0

Почему вы не можете использовать '_currentUser'? – markpsmith

+0

@markpsmith, _currentUser является переменной-членом моего контроллера, которая зависит от текущего HttpContext. Я могу использовать его в моем контроллере, но я не могу использовать его в конструкторе ViewModel, поскольку у меня нет чистого способа доступа к HttpContext. – cpaulus

+0

Предполагая, что вы используете MVC5 и C# 5, можете ли вы попробовать это? общественная организацияType? OrganizationType {get; set;} = null; // или любое другое значение, которое вы хотите установить по умолчанию –

ответ

0

Хорошо, я думаю, я нашел решение моей проблемы ...

я могу использовать ModelState свойства в контроллере, чтобы проверить его модель представление является пустым или был переплетен из формы:

public ActionResult Search(SearchViewModel vm = null) 
{ 

    if (ModelState.Count == 0) 
    {   
     InitViewModel(vm); 
    }  
    ... 
    return View(vm); 
} 

Так что если ModelState.Count равен 0, это означает, что пользователь не изменять какие-либо фильтры. Таким образом, форма пуста, и мы можем привязать наши значения по умолчанию. Как только пользователь изменит один из фильтров или отправит запрос, модель ModelState.Count будет больше 0, поэтому мы не должны устанавливать значение по умолчанию. В противном случае мы переопределили бы выбор пользователя.

0

Логика того, что вы делаете, немного немного. Вообще говоря, если значение является нулевым, то значение null является значением по умолчанию. Однако кажется, что вы пытаетесь сделать здесь различие между тем, является ли значение нулевым, потому что оно не установлено или равно нулю, поскольку пользователь явно установил его равным нулю. Этот тип семантической дисперсии обычно является плохой идеей. Если значение null имеет значение, оно всегда должно иметь это значение. В противном случае ваш код становится более запутанным, и в результате обычно появляются ошибки.

Тем не менее, вы не можете рассчитывать на ModelState, не имея предметов. Я честно никогда не играл с ModelState в сценариях, где нет данных для публикации, но возможно, есть сценарий, в котором нет данных для сообщения, и у ModelState могут быть элементы. Даже если это не так, это детализация реализации. Что делать, если Microsoft делает обновление, которое добавляет элементы в ModelState в ситуациях, когда у него ранее не было ни одного. Затем ваш код ломается без видимой причины.

Единственное, на что вы действительно можете рассчитывать, - это метод запроса GET или POST. В версии GET вашего действия вы можете с полным основанием предположить, что пользователь не внес изменений. Поэтому в этом сценарии вы можете просто установить значение в любое удобное для вас без проблем.

В версии POST вашего действия пользователь произвел какую-то модификацию. Однако на данный момент нет никакого способа различить, является ли значение нулевым, потому что оно или потому, что пользователь явно хотел, чтобы это было. Поэтому вы должны уважать значение as-is.

+0

Я согласен, что сделать различие между «значением по умолчанию null» и нулевым значением, установленным пользователем, не самая лучшая идея. Но я хочу, чтобы моя инициализация ViewModel была простой. Установка значения по умолчанию для пользователя somes - это особый случай, а не общность. Меня интересует только запрос GET, запрос поступает из HTML-формы, поэтому пользователь, возможно, внес изменения. – cpaulus

Смежные вопросы