1

Я использую DataAnnotations для проверки ошибок в моем приложении asp.net mvc, я также использую строго типизированные ViewModels.asp.net mvc multiselect запомнить состояние после обратной передачи

Моя проверка ошибок работает нормально и отправляет обратно к моему представлению сообщения об ошибках, если поле пустое. Однако у меня есть MultiSelect/Listbox в моей форме, который мне нужно запомнить, это состояние после ошибки.

На данный момент мой ViewModel выглядит следующим образом (я только включены соответствующие свойства):

public class ProfilePageViewModel : PageViewModel 
{ 
    public IList<FavouriteGenreViewModel> FavGenres { get; set; } 

    [Required(ErrorMessage = "*")] 
    public string SelectedGenres { get; set; } 


    public IDictionary<int, string> GenresList { get; set; } 
} 

Это мое действие в мой контроллер:

public ActionResult Profile(ProfilePageViewModel viewModel) 
    { 
     if(!ModelState.IsValid) 
     { 
      viewModel.CountriesList = dropDownTasks.GetCountries(); 
      viewModel.GendersList = dropDownTasks.GetGenders(); 
      viewModel.GenresList = dropDownTasks.GetGenres(); 
      viewModel.TimezonesList = dropDownTasks.GetTimezones(); 
      viewModel.FavGenres = 
      return View(viewModel); 
     } 

     . . . 

Мой MultiSelect принимает список FavouriteGenreViewModel-х для выбора параметров в GenresList, он делает это с помощью AutoMapper в действии GET, но, очевидно, я не могу использовать AutoMapper в сообщении, потому что он забудет мои опубликованные значения.

Я думал об использовании запятой delimmated строки идентификаторов вместо списка FavouriteGenreViewModel, таким образом, я могу повторно использовать значение, однажды отправленное назад ... однако я надеюсь, что у кого-то есть более элегантный способ иметь дело с Эта проблема.

Спасибо!

Пол

ответ

2

Я думаю, что я могу ответить на мой собственный вопрос после того, как некоторые ковыряться.

В моей ViewModel я использовать массив строк в качестве типа данных, как так:

public class ProfilePageViewModel : PageViewModel 
{ 
[Required(ErrorMessage = "*")] 
public string[] FavGenres { get; set; } 

public IDictionary<int, string> GenresList { get; set; } 
} 

На мой взгляд, я могу установить выбранные значения FavGenres, то у меня есть пользовательские модели связующего для преобразования через запятую строка в действительные объекты снова ... в случае, если вам интересно, это мое собственное связующее устройство в полном объеме ...

public class AccountCustomModelBinder : DefaultModelBinder 
{ 
    private readonly IGenreRepository genreRepository; 
    private readonly ITimezoneRepository timeZoneRepository; 
    private readonly ICountryRepository countryRepository; 

    public AccountCustomModelBinder() : this(
     ServiceLocator.Current.GetInstance<IGenreRepository>(), 
     ServiceLocator.Current.GetInstance<ITimezoneRepository>(), 
     ServiceLocator.Current.GetInstance<ICountryRepository>()) 
    { 
    } 

    public AccountCustomModelBinder(IGenreRepository genreRepository, ITimezoneRepository timeZoneRepository, 
     ICountryRepository countryRepository) 
    { 
     Check.Require(genreRepository != null, "genreRepository is null"); 
     Check.Require(timeZoneRepository != null, "timeZoneRepository is null"); 
     Check.Require(countryRepository != null, "countryRepository is null"); 

     this.genreRepository = genreRepository; 
     this.timeZoneRepository = timeZoneRepository; 
     this.countryRepository = countryRepository; 
    } 

    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor) 
    { 
     Account account = bindingContext.Model as Account; 

     if (account != null) 
     { 

      // gender 
      if (propertyDescriptor.Name == "Gender") 
      { 
       if (bindingContext.ValueProvider.ContainsKey("Gender")) 
       { 
        account.Gender = bindingContext.ValueProvider["Gender"].AttemptedValue.ToString(); 
        return; 
       } 
      } 

      // TimezoneId 
      if (propertyDescriptor.Name == "TimezoneId") 
      { 
       if (bindingContext.ValueProvider.ContainsKey("TimezoneId")) { 
        account.Timezone = timeZoneRepository.FindOne(Convert.ToInt32(bindingContext.ValueProvider["TimezoneId"].AttemptedValue)); 
        return; 
       } 
      } 

      // CountryId 
      if (propertyDescriptor.Name == "CountryId") 
      { 
       if (bindingContext.ValueProvider.ContainsKey("CountryId")) { 
        account.Country = countryRepository.FindOne(Convert.ToInt32(bindingContext.ValueProvider["CountryId"].AttemptedValue)); 
        return; 
       } 
      } 

      // FavGenres 
      if (propertyDescriptor.Name == "FavGenres") 
      { 
       if (bindingContext.ValueProvider.ContainsKey("FavGenres")) { 
        // remove all existing entries so we can add our newly selected ones 
        account.ClearFavGenres(); 
        string favIds = bindingContext.ValueProvider["FavGenres"].AttemptedValue; 
        foreach (string gId in favIds.Split(',')) { 
         account.AddFavGenre(genreRepository.Get(Convert.ToInt32(gId))); 
        } 
        return; 
       } 
      } 
     } 

     base.BindProperty(controllerContext, bindingContext, propertyDescriptor); 
    } 

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