-->

MVC-3 DropdownList or DropdownListFor - Can't

2019-08-02 20:34发布

问题:

I searches for hours (or days) and didn't find a solution yet. I want to edit a customer with a DropdownListFor for the salutation with the right preselected value.

I've got 3 entities (Database first concept, this is not my own design...): customer, address, salutation

A CUSTOMER has an address_id (f_key) and an ADDRESS has got a salutation_id (f_key). The ADDRESS holds the first and last name for example. Inside the SALUTATION entity there is a column sal1 which holds all possible salutations.

Now, I want to edit my customer via a ViewModel which looks like this:

public class CustomerViewModel
{
    public CUSTOMER cust { get; set; }
    public SelectList salutationList { get; set; }

    CustomerRepository repository = new CustomerRepository();

    public CustomerViewModel(int id)
    {
        cust = repository.GetCustomerByIdAsQueryable(id).Single();
        salutationList = new SelectList(repository.GetSalutations(), cust.ADDRESS.SALUTATION.SAL1);
    }
    // Some more
}

The CutsomerRepository methods:

public class CustomerRepository
    {
        private MyEntities db = new MyEntities();

        public IQueryable<CUSTOMER> GetCustomerByIdAsQueryable(int id) {...}

        public IQueryable<CUSTOMER> GetCustomersByName(string firstName, string lastName, int maxCount)  {...}

        public List<string> GetSalutations()
        {
            var salutationList = new List<string>();
            var salutationListQry = from s in db.SALUTATION
                                    select s.SAL1;
            salutationListTemp.AddRange(salutationListQry);
            return salutationList;
        }
        // ...
    }

This is my controller method:

[HttpPost]
public ActionResult CustomerData(int id, FormCollection fc)
{
    var vm = new CustomerViewModel(id);
    // Why do I need the following line?
    vm.cust = repository.GetCustomerByIdAsQueryable(id).Single();
    try
    {
        UpdateModel(vm, fc);
        repository.Save();
        return View("CustomerData", vm);
    }
    catch (Exception e)
    {
        return View();
    }
}

And finally the part from my View:

@model WebCRM.ViewModels.CustomerViewModel
@using (Html.BeginForm())
{
    // ...
    <div class="editor-label">
        @Html.Label("Salutation:")
        @Html.DropDownListFor(model => model.cust.ADDRESS.SALUTATION.SAL1, Model.salutationList)
        // @Html.DropDownList("Salutation", Model.salutationList)
    </div>
    <div class="editor-label">
    </div>
    <div class="editor-field">
        @Html.Label("Last name:")
        @Html.EditorFor(model => model.cust.ADDRESS.LASTNAME)
        @Html.ValidationMessageFor(model => model.cust.ADDRESS.LASTNAME)
    </div>
    <p>
        <input type="submit" value="Speichern" />
    </p>
}

Changing and saving last names works fine. But when saving the salutation it changes the SAL1 value in the SALUTATION entity to the one I've chosen in the DropdownListFor. What I want is to change the salutation_id inside the ADDRESS entity for my customer. Why isn't that working?

Another strange behavoior: When removing the marked line in my CustomerController, I can't even change and save the last name. Normally the constructor of the CustimerViewModel sets the customer. So why do I have to have the line of code for setting the customer inside my ViewModel? It's duplicated, but has to be there...

Thanks in advance.

回答1:

You need to have Selected property in your list.

I can show you my working example:

public static IEnumerable<SelectListItem> GetCountries(short? selectedValue)
    {
        List<SelectListItem> _countries = new List<SelectListItem>();
        _countries.Add(new SelectListItem() { Text = "Select country...", Value = "0", Selected = selectedValue == 0 });
        foreach (var country in ObjectFactory.GetInstance<DataRepository>().GetCountries())
        {
            _countries.Add(new SelectListItem()
            {
                Text = country.Name,
                Value = country.ID.ToString(),
                Selected = selectedValue > 0 && selectedValue.Equals(country.ID)
            });
        }
        return _countries;
    }  

In controller i store this into viewbag:

ViewBag.Countries = CompanyModel.GetCountries(0);

In view:

@Html.DropDownListFor(m => m.CompanyModel.CountryId, (IEnumerable<SelectListItem>)ViewBag.Countries)