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

}