While you could use an ExceptionFilter, its is unnecessary. The real problem here is you incorrect use of a view model. A view model should contain only properties your need for display/edit in the view and should not access the database. Two reasons for this are
- You can not unit test the model or any component of your app,
including the controller, that uses the model. Even though its clear
your not yet into unit testing, you should at least design for it (I
guarantee that once you do, you it will become an integral part of
your development).
- Because your will be posting back your view model, it means that the
DefaultModelBinderwill initialize the model and call its
constructor which in turn calls the database to populate yourSelectList. The only reason you should need theSelectListin
the POST method is becauseModelStateis invalid and you need to
return the view. If client side validation is enabled, this would be
rare, so you unnecessarily degrading performance by making database
calls for data that wont be used.
Suggest you read the answers in What is ViewModel in MVC?
Next, your GET method should not contain a parameter for you model. Two reasons for this are
- The DefaultModelBinderis initializing your model and it
adds the values of your model properties toModelStateand if your
properties contain any validation attributes, thenModelStatewill
be invalid. The side affect will be that any validation errors will
be displayed in the initial view, and any attempt to set the value
of your properties in the GET method will be ignored byHtmlHelpermethods because they use the values fromModelStatein preference
to the model properties. To overcome this, you would need to use theModelState.Clear()hack, effectively undoing what theModelBinderhas just done. Again its just pointless extra
overhead.
- Because you cannot have the same signature for the GET and POST
method, you need to rename the POST method and use the overload of
BeginForm()that specifies the action method name.
Instead, you should be initializing an instance of the view model inside the GET method.
Finally the code in your models constructor to generate the SelectList is generating one IEnumerable<SelectListItem> and then creating a second identical IEnumerable<SelectListItem> from the first one (again its just unnecessary extra overhead).
From your comments, you have indicated that this will be a base view model, so I would suggest that you have a BaseController with the following method
protected void ConfigureBaseViewModel(BaseVM model)
{
  List<X> xs = GetItemsFromDB();
  model.SelectListModel = new SelectList(xs, "value", "text");
  // or model.SelectListModel = xs.Select(x => new SelectListItem{ Value = x.value, Text=x.text });
}
where BaseVM is
public abstract class BaseVM
{
  [Required(ErrorMessage = "Please select an item")] // add other display and validation attributes as necessary
  public int SelectedItem { get; set; } // or string?
  public IEnumerable<SelectListItem> SelectListModel { get; set; }
  .... // other common properties
}
and then in the concrete controller
public ActionResult Index()
{
  var model = new yourConcreteModel();
  ConfigureBaseViewModel(model);
  return View(model);
}
[HttpPost]
public ActionResult Index(yourConcreteModel model)
{
  if (!ModelState.IsValid)
  {
    ConfigureBaseViewModel(model);
    return View(model);
  }
  // save and redirect
}
Similarly you might have aprivate void ConfigureConcreteViewModel(yourConcreteModel model) method in each concrete controller that assigns common values such as SelectLists that are needed in the GET method and POST method if the view needs to be returned.