简体   繁体   中英

How should i structure my View Model - ASP.NET MVC

I am wanting to create a survey using ASP.NET MVC 3.0. Some questions will have radio buttons and some check boxes. I want to know the correct syntax for my View side as well as my ViewModel. I want to store my options for the answers in a Collection. Would IEnumerable be a good collection to use? Here is some of my ViewModel code.

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

What is the best way to get the information into my ViewModel when my build method is called? Should i be using IEnumerable or just strings?

here is my code on my .aspx page.

<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>

I am new to ASP.NET MVC but I have experience with both ASP.NET and the MVC pattern. I want as much emphasis placed on seperation of concerns as possible.

My controller class calls my build method. I have a Service class which grabs a Repository object which will be grabbing information from my Model/Database.

! I want my Radio buttons to be dynamically taken from my Database. And then if the user already has something selected from a previous session i want that to be found in my ViewModel and already selected when they load the page.

The problem I see with your approach above is that your Radio Buttons and Check Boxes are defined in your View. This is obviously a problem if they are coming out of a database or an enum or something. What you should do is add a ViewModel property that represents all the possible options for a given radio/checkbox group, as well as a property that holds the selected values that the user chose for that group.

First, check out these GREAT helper methods for " CheckBoxListFor " and " RadioButtonListFor ". Copy them into your project.

Next, you need to expose your collections on the ViewModel as IEnumerable<SelectListItem> . These are the possible options for your radiolist/checkboxlist/dropdown element.

Then, your ViewModel, you will need to define a prop for a single selected option (from a Dropdown or a radio button list) or a collection of the selected option (from a Checkbox list). You can use int/string from the item's database ID, or if the type to be selected is an enum, you can bind directly to that.

Finally, your View become SUPER SIMPLE, and won't need to be touched if you add new options. In the case of database-driven options, no code at all has to change.

Below is a sample from a demo page I have open. I believe you should be able to look at it and apply it to your own project.

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

The Domain Model class and the method to provide the collections:

 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,
        }

And the super-simplified View:

@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" />
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM