1

我使用DataAnnotations進行錯誤檢查,在我的asp.net mvc應用程序中,我也使用強類型的ViewModels。asp.net mvc multiselect回覆後記住狀態

我的錯誤檢查工作正常,並回傳到我的觀點與錯誤消息,如果一個字段爲空。不過,我的表單上有一個MultiSelect/Listbox,我需要記住錯誤發生後的狀態。

此刻我的視圖模型看起來像這樣(我只包括相關屬性):

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); 
     } 

     . . . 

我多選需要FavouriteGenreViewModel的列表要選擇GenresList中的選項,它會在GET操作中使用AutoMapper執行此操作,但顯然我無法在帖子中使用AutoMapper,因爲它會忘記我發佈的值。

我想過使用ID的逗號分隔字符串而不是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); 
    } 

}