我应该如何构建我的视图模型 - ASP.NET MVC

时间:2013-02-07 22:57:18

标签: c# asp.net-mvc asp.net-mvc-3 model-view-controller viewmodel

我想使用ASP.NET MVC 3.0创建调查。有些问题会有单选按钮和一些复选框。我想知道我的View端以及ViewModel的正确语法。 我想在Collection中存储我的答案选项。 IEnumerable会成为一个很好的集合吗?这是我的一些ViewModel代码。

    [DisplayName("Country")]
    [Required(ErrorMessage = "Country is required.")]
    public string Country { get; set; }

    public IEnumerable<string> Countries { get; set; }

    [DisplayName("Business")]
    [Required(ErrorMessage = "Please select a business unit.")]
    public string BusinessUnit { get; set; }

    public IEnumerable<string> Businesses { get; set; }

    public Boolean ToGetFit { get; set; }
    public Boolean ToChallengeMyself { get; set; }      
    public Boolean ToBeHealthier { get; set; }
    public Boolean ChallengeOther { get; set; }
    public string OtherString { get; set; }

    public void build()
    {
        var myService = new SurveyService(new SurveyRepository());
        Name = myService.getName();
        Email = myService.getEmail();
    }      

调用构建方法时,将信息导入ViewModel的最佳方法是什么? 我应该使用IEnumerable还是只使用字符串?

这是我的.aspx页面上的代码。

<li>    What country do you live in? <br />   
    <%= Html.RadioButtonFor(model => model.Country, "Canada", true) %> Ecuador<br />   
    <%= Html.RadioButtonFor(model => model.Country, "Chile", true) %> Ghana   <br />
    <%= Html.RadioButtonFor(model => model.Country, "Italy", true) %> Nigeria   <br />
    <%= Html.RadioButtonFor(model => model.Country, "Germany", true) %> Romania   
</li>

<li> What business unit do you work in?<br />
    <%= Html.RadioButtonFor(model => model.BusinessUnit, "Pharmaceuticals", true ) %> Pharmaceuticals <br />        
    <%= Html.RadioButtonFor(model => model.BusinessUnit, "Mechanics", true) %> Vaccines  <br />
    <%= Html.RadioButtonFor(model => model.BusinessUnit, "R&D") %> R&D   <br />
    <%= Html.RadioButtonFor(model => model.BusinessUnit, "Distribution", true) %> Distribution   <br />
</li>           

<li>    Why do you want to take part in this workout? <br />
    <%= Html.CheckBoxFor(model => model.ToGetFit ) %>   To get in shape   <br />
    <%= Html.CheckBoxFor(model => model.ToChallengeMyself ) %> To challenge myself     <br />       
    <%= Html.CheckBoxFor(model => model.ToBeHealthier) %>   To be healthier     <br />
    <%= Html.CheckBoxFor(model => model.ChallengeOther) %>  Other  
    <%= Html.TextBoxFor(model => model.OtherString) %>
</li>

我是ASP.NET MVC的新手,但我有ASP.NET和MVC模式的经验。 我希望尽可能重视分离问题。

我的控制器类调用我的构建方法。我有一个Service类,它抓取一个Repository对象,它将从我的Model / Database中获取信息。

!我希望我的单选按钮可以从我的数据库中动态获取。然后,如果用户已经从之前的会话中选择了某些内容,我希望在我的ViewModel中找到该内容并在加载页面时选择该内容。

1 个答案:

答案 0 :(得分:4)

我在上面的方法中看到的问题是您的单选按钮和复选框是在视图中定义的。如果它们来自数据库或枚举或其他东西,这显然是一个问题。您应该做的是添加一个ViewModel属性,该属性表示给定radio / checkbox组的所有可能选项,以及包含用户为该组选择的选定值的属性。

首先,查看&#34; CheckBoxListFor&#34;的这些 GREAT 辅助方法。和&#34; RadioButtonListFor&#34;。将它们复制到您的项目中。

接下来,您需要将ViewModel上的集合公开为IEnumerable<SelectListItem>。这些是您的radiolist / checkboxlist / dropdown元素的可能选项。

然后,您的ViewModel,您需要为单个选定选项(来自下拉列表或单选按钮列表)或所选选项的集合(来自复选框列表)定义道具。您可以使用项目数据库ID中的int / string,或者如果要选择的类型是枚举,则可以直接绑定到该项。

最后,您的视图变得非常简单,如果您添加新选项,则无需触及。对于数据库驱动的选项,根本不需要更改任何代码。

以下是我打开的演示页面中的示例。我相信你应该能够看到并将它应用到你自己的项目中。

ViewModel:

public class OrderViewModel
    {
        public int FavoriteMovieID { get; set; }
        public List<int> MovieIdsForMoviesILike { get; set; }

        public MovieCategories FavoriteMovieType { get; set; }
        public List<MovieCategories> MovieCategoriesILike { get; set; }

        public IEnumerable<SelectListItem> MoviesToSelectFrom 
        {
            get
            {
                return from x in OrderDetailsRepo.GetAllMovies()
                       select new SelectListItem {
                           Text = x.Title,
                           Value = x.ID.ToString(),
                           Selected = MovieIdsForMoviesILike.Contains(x.ID),
                       };
            }
        }

        public IEnumerable<SelectListItem> MovieCategoriesToSelectFrom
        {
            get
            {
                return from cat in Enum.GetValues(typeof(MovieCategories)).Cast<MovieCategories>()
                       select new SelectListItem {
                           Text = cat.ToString(),
                           Value = cat.ToString(),
                           Selected = MovieCategoriesILike.Contains(cat),
                       };
            }
        }

        public OrderViewModel()
        {
            // to ensure they are never NULL
            MovieIdsForMoviesILike = new List<int>();
            MovieCategoriesILike = new List<MovieCategories>();
        }
}

Domain Model类和提供集合的方法:

 public static class OrderDetailsRepo
        {
            public static List<Movie> GetAllMovies()
            {
                return new List<Movie> {
                    new Movie { ID = 0, Title = "Great Expectation" },
                    new Movie { ID = 1, Title = "Gone with the Wind" },
                    new Movie { ID = 2, Title = "Lion of Winter" },
                };
            }
        }

    public class Movie
        {
            public string Title { get; set; }
            public int ID { get; set; }
        }

    public enum MovieCategories
        {
            Horror,
            Drama,
            Comedy,
        }

超简化的视图:

@model MVC3App.ViewModels.OrderViewModel
@using MVC3App.MVCHtmlHelpers @* RadioButtonList and CheckBoxList are defined in here *@

@{
    ViewBag.Title = "ViewPage1";
}

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    <div class="editor-label">
        What's your favorite movie?
    </div>
    <div class="editor-field">
        @Html.RadioButtonListFor(model => model.FavoriteMovieID, Model.MoviesToSelectFrom)
        @Html.ValidationMessageFor(model => model.FavoriteMovieID)
    </div>

    <div class="editor-label">
        What movies do you like in general?
    </div>
    <div class="editor-field">
        @Html.CheckboxListFor(model => model.MovieIdsForMoviesILike, Model.MoviesToSelectFrom)
        @Html.ValidationMessageFor(model => model.MovieIdsForMoviesILike)
    </div>

    <div class="editor-label">
        What's your favorite Movie Genre?
    </div>
    <div class="editor-field">
        @Html.RadioButtonListFor(model => model.FavoriteMovieType, Model.MovieCategoriesToSelectFrom)
        @Html.ValidationMessageFor(model => model.FavoriteMovieType)
    </div>

    <div class="editor-label">
        What Movie Genres do you like in general?
    </div>
    <div class="editor-field">
        @Html.CheckboxListFor(model => model.MovieCategoriesILike, Model.MovieCategoriesToSelectFrom)
        @Html.ValidationMessageFor(model => model.MovieCategoriesILike)
    </div>

    <br /><br />
    <input type="submit" value="Save" />
}