asp.net mvc 多选记住回发后的状态

发布于 2024-08-17 18:51:42 字数 1272 浏览 6 评论 0原文

我正在使用 DataAnnotations 对我的 asp.net mvc 应用程序进行错误检查,我也使用强类型 ViewModel。

我的错误检查工作正常,如果字段为空,则会将错误消息发回我的视图。但是,我的表单上有一个多选/列表框,我需要记住它在发生错误后的状态。

目前我的 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 中的选项,它在 GET 操作中使用 AutoMapper 来执行此操作,但是显然我不能在帖子上使用 AutoMapper,因为它会忘记我发布的值。

我考虑过使用逗号分隔的 ID 字符串而不是 FavouriteGenreViewModel 列表,这样我就可以重新使用回发后的值...但是我希望有人有一种更优雅的方式来处理这个问题。

谢谢你!

保罗

I am using the DataAnnotations for error checking on my asp.net mvc app, I am also using strongly typed ViewModels too.

My error checking is working fine and is posting back to my view with error messages if a field is blank. However i have a MultiSelect / Listbox on my form which i need to remember it's state after an error.

At the moment my ViewModel looks like this (i have only included relevant properties):

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

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


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

This is my Action in my controller:

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

        . . .

My MultiSelect takes a list of FavouriteGenreViewModel's to select the options in the GenresList, it does this using AutoMapper in GET action, but obviouslly i can't use AutoMapper on the post because it will forget my posted values.

I have thought about using a comma delimmated string of ID's instead of a list of FavouriteGenreViewModel's, that way i can re-use the value once posted back...however i am hoping someone has a more elegant way of dealing with this problem.

Thank you!

Paul

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

巨坚强 2024-08-24 18:51:42

我想经过一番探索后我可以回答我自己的问题。

在我的 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);
    }

}

I think i can answer my own question after some poking around.

In my ViewModel i use a string array as the Data Type like so:

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

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

In my view i can set the selected values to FavGenres, then i have a custom model binder to convert the comma seperated string into valid objects again...in case you are wondering here is my custom model binder in full...

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文