0

I have populated a dropdown list with values from Database Table. The list gets populated with correct table data but all values have ZERO index in the list. Here is the code to fill dropdown list:

//Get
public ActionResult NewBooking()
{
        var db = new VirtualTicketsDBEntities2();

        IEnumerable<SelectListItem> items = db.Attractions
            .ToList()
            .Select(c => new SelectListItem
          {
              Value = c.A_ID.ToString(),
              Text = c.Name
          });
        ViewBag.Attractions = items;
        return View();
}

And on Dropdown View Page:

<div class="editor-label">
        @Html.LabelFor(model => model.Attraction)
    </div>
    <div class="editor-field">
        @Html.DropDownList("Attractions")
</div>

For example if table have 3 values A,B, and C. These values are appearing in dropdown list but when I get its selected index in POST request function, it always returns ZERO. Here is the POST submit function:

//Post
    [HttpPost]
    public ActionResult NewBooking(BookingView booking)
    {
        try
        {
            BookingManager bookingManagerObj = new BookingManager();
            bookingManagerObj.Add(booking);
            ViewBag.BookingSavedSucess = "Booking saved!";
            return View("WelcomeConsumer","Home");
        }
        catch
        {
            return View(booking);
        }
    }

booking.Attraction is always ZERO even user selected greater than ZERO index item.

Any suggestions?

4

3 回答 3

1

I would guess that it is because you are getting a collection of SelectListItems back and not an actual SelectList. Try something like:

<div class="editor-field"> @Html.DropDownListFor(model => model.Attraction, new SelectList(ViewBag.Attractions, "Value", "Text");

于 2013-07-18T17:29:49.550 回答
0

It's best not to use ViewBag, you should always use a ViewModel.

Say you have a ViewModel like this:

public class AttractionViewModel
{
    public int AttractionId { get; set; }
    public SelectList Attractions { get; set; }
}

and modify your view like this - I presume you already have a form in there, the relevant bit is the @Html.DropDownListFor(...) and making sure you have the full namespace to the ViewModel if you haven't already included it in the Views web.config file:

@model AttractionViewModel
@using(Html.BeginForm("NewBooking", "ControllerName"))
{
    <div class="editor-label">
        @Html.LabelFor(model => model.AttractionId)
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(model => model.AttractionId, Model.Attractions)
    </div>
    <input type="submit" value="Submit">
}

and modify your HttpGet like this:

//Get
public ActionResult NewBooking()
{
    var db = new VirtualTicketsDBEntities2();
    var items = db.Attractions.ToList();
    var attractionIdDefault = 0;// default value if you have one
    var vm = new AttractionViewModel {
        AttractionId = attractionIdDefault,// set this if you have a default value
        Attractions = new SelectList(items, "A_ID", "Name", attractionIdDefault)
    }    
    return View(vm);
}

and create an HttpPost ActionResult like this:

// Post
public ActionResult NewBooking(AttractionViewModel vm)
{
    var attractionId = vm.AttractionId; // You have passed back your selected attraction Id.
    return View();
}

Then it should work.

于 2013-07-18T17:41:46.587 回答
0

I know that you have already selected your answer but here is an alternative way of doing what you did. When I started off with ASP.NET MVC I struggled with SelectListItem and found another way of populating my drop down list. I have stuck to this way ever since.

I always have a view model that I bind to my view. I never send through a domain model, always a view model. A view model is just a scaled down version of your domain model and can contain data from multiple domain models.

I have made some modifications to your code and tips, but like I mentioned, it's just an alternative to what you already have.

Your domain model could look like this. Try and give your property names some meaningful descriptions:

public class Attraction
{
     public int Id { get; set; }

     public string Name { get; set; }
}

You view model could look something like this:

public class BookingViewModel
{
     public int AttractionId { get; set; }

     public IEnumerable<Attraction> Attractions { get; set; }

     // Add your other properties here
}

Do not have your data access methods in your controllers, rather have a service layer or repository expose this functionality:

public class BookingController : Controller
{
     private readonly IAttractionRepository attractionRepository;

     public BookingController(IAttractionRepository attractionRepository)
     {
          this.attractionRepository = attractionRepository;
     }

     public ActionResult NewBooking()
     {
          BookingViewModel viewModel = new BookingViewModel
          {
               Attractions = attractionRepository.GetAll()
          };

          return View(viewModel);
     }

     [HttpPost]
     public ActionResult NewBooking(BookingViewModel viewModel)
     {
          // Check for null viewModel

          if (!ModelState.IsValid)
          {
               viewModel.Attractions = attractionRepository.GetAll();

               return View(viewModel);
          }

          // Do whatever else you need to do here
     }
}

And then your view will populate your drop down like this:

@model YourProject.ViewModels.Attractionss.BookingViewModel

@Html.DropDownListFor(
     x => x.AttractionId,
     new SelectList(Model.Attractions, "Id", "Name", Model.AttractionId),
     "-- Select --"
)
@Html.ValidationMessageFor(x => x.AttractionId)

I hope this helps.

于 2013-07-19T08:54:36.313 回答