我在MVC中创建了一个简单的搜索页面,其中包含一些过滤器。过滤器由我的ViewModel中的属性表示。我的ViewModel绑定到cshtml中的GET表单,因此我的过滤器将出现在查询字符串中,用户可以为他的搜索添加书签。
我想要做的是为我的某些过滤器分配一个默认值。
我的(简化)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 值对应于空过滤器,并且它是用户可以做出的选择。所以我无法覆盖它。
我尝试的第二个解决方案是在搜索操作中指定控制器的默认值应为null:
public ActionResult Search(SearchViewModel vm = null)
{
if (vm == null)
{
vm = new SearchViewModel();
InitViewModel(vm);
}
...
return View(vm);
}
但实际上,变量 vm 永远不会为空,因此永远不会设置默认值。
我还尝试过两个Action,一个没有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与某些值从表单绑定的ViewModel。
有什么想法吗?
答案 0 :(得分:0)
好的我觉得我找到了解决自己问题的方法......
我可以使用控制器的 ModelState 属性来检查ViewModel是为空还是从表单绑定:
public ActionResult Search(SearchViewModel vm = null)
{
if (ModelState.Count == 0)
{
InitViewModel(vm);
}
...
return View(vm);
}
因此,如果 ModelState.Count 等于0,则表示用户未更改任何过滤器。因此表单为空,我们可以绑定默认值。一旦用户更改其中一个过滤器或提交请求, ModelState.Count 将大于0,因此我们不应设置默认值。否则我们会覆盖用户选择。
答案 1 :(得分:0)
你正在做的事情的逻辑有点不确定。一般来说,如果值可以为空,那么null是默认值。但是,您似乎正在尝试区分值是否为null,因为它未设置或为null,因为用户将其显式设置为null。这种语义差异通常是一个坏主意。如果null有意义,那么它应该始终具有该含义。否则,您的代码会变得更加混乱,因此通常会引入错误。
尽管如此,你不能指望ModelState
没有物品。老实说,在没有发布数据的情况下,ModelState
从未玩过ModelState
,但在某些情况下可能没有帖子数据但ModelState
可能有项目。即使没有,这也是一个实现细节。如果Microsoft在以前没有项目的情况下执行将项目添加到import pandas as pd
%matplotlib inline
df =pd.read_csv(‘C:/Users/caol3/Downloads/Data Sampler.csv’)
IOErrorTraceback (most recent call last)
<ipython-input-3-3740a47c4f96> in <module>()
----> 1 df =pd.read_csv('C:/Users/caol3/Downloads/Data Sampler.csv')
/opt/conda/envs/python2/lib/python2.7/site-packages/pandas/io/parsers.pyc in parser_f(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, escapechar, comment, encoding, dialect, tupleize_cols, error_bad_lines, warn_bad_lines, skip_footer, doublequote, delim_whitespace, as_recarray, compact_ints, use_unsigned, low_memory, buffer_lines, memory_map, float_precision)
560 skip_blank_lines=skip_blank_lines)
561
--> 562 return _read(filepath_or_buffer, kwds)
563
564 parser_f.__name__ = name
/opt/conda/envs/python2/lib/python2.7/site-packages/pandas/io/parsers.pyc in _read(filepath_or_buffer, kwds)
313
314 # Create the parser.
--> 315 parser = TextFileReader(filepath_or_buffer, **kwds)
316
317 if (nrows is not None) and (chunksize is not None):
/opt/conda/envs/python2/lib/python2.7/site-packages/pandas/io/parsers.pyc in __init__(self, f, engine, **kwds)
643 self.options['has_index_names'] = kwds['has_index_names']
644
--> 645 self._make_engine(self.engine)
646
647 def close(self):
/opt/conda/envs/python2/lib/python2.7/site-packages/pandas/io/parsers.pyc in _make_engine(self, engine)
797 def _make_engine(self, engine='c'):
798 if engine == 'c':
--> 799 self._engine = CParserWrapper(self.f, **self.options)
800 else:
801 if engine == 'python':
/opt/conda/envs/python2/lib/python2.7/site-packages/pandas/io/parsers.pyc in __init__(self, src, **kwds)
1211 kwds['allow_leading_cols'] = self.index_col is not False
1212
-> 1213 self._reader = _parser.TextReader(src, **kwds)
1214
1215 # XXX
pandas/parser.pyx in pandas.parser.TextReader.__cinit__ (pandas/parser.c:3427)()
pandas/parser.pyx in pandas.parser.TextReader._setup_parser_source (pandas/parser.c:6861)()
IOError: File C:/Users/caol3/Downloads/Data Sampler.csv does not exist
的更新,该怎么办?然后,你的代码中断没有明显的原因。
您唯一可以依赖的是请求方法是GET还是POST。在您的操作的GET版本中,您可以合理地假设用户未进行任何修改。因此,在这种情况下,您可以毫无顾虑地将值设置为您喜欢的任何值。
在您的操作的POST版本中,用户进行了某种修改。但是,此时,无法再区分该值是否为null,因为它是或因为用户明确希望它。因此,您必须按原样尊重该值。