Объединение нескольких моделей в одно представление - создание проблемы - PullRequest
0 голосов
/ 23 июля 2011

Я пытаюсь объединить адреса и адреса создания страны в одно представление. Я использую MVC 3 с Repository Scaffolding и ASPX Views. В настоящее время у меня есть раскрывающийся список Страна, который уже заполнен, и я пытаюсь добавить его в представление «Создание адреса». У меня Edit View работает просто отлично. Однако, когда я пытаюсь создать новый адрес, он добавляет новую страну с пустым именем, хотя я выбираю страну в раскрывающемся списке. Я чувствую, что упускаю что-то очень фундаментальное, потому что это должно быть легко.

Классы POCO

public class Address
{
    public int ID { get; set; }
    public string Street1 { get; set; }
    public string Street2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    [ForeignKey("Country")]
    public int CountryID { get; set; }
    public Country Country { get; set; }
}

public class Country
{
    public int ID { get; set; }
    [Display(Name = "Country"), MaxLength(50)]
    public string Name { get; set; }
}

Адресный контроллер

public class AddressController : Controller
{
    private readonly IAddressRepository addressRepository;
    private readonly ICountryRepository countryRepository;

    // If you are using Dependency Injection, you can delete the following constructor
    public AddressController() : this(new AddressRepository(), new CountryRepository())
    {
    }

    public AddressController(IAddressRepository addressRepository, ICountryRepository countryRepository)
    {
        this.addressRepository = addressRepository;
        this.countryRepository = countryRepository;
    }

    //
    // GET: /Address/

    public ViewResult Index()
    {
        return View(addressRepository.All);
    }

    //
    // GET: /Address/Details/5

    public ViewResult Details(int id)
    {
        return View(addressRepository.Find(id));
    }

    //
    // GET: /Address/Create

    public ActionResult Create()
    {
        ViewBag.PossibleCountries = countryRepository.All;
        return View();
    } 

    //
    // POST: /Address/Create

    [HttpPost]
    public ActionResult Create(Address address)
    {
        if (ModelState.IsValid) {
            addressRepository.InsertOrUpdate(address);
            addressRepository.Save();
            return RedirectToAction("Index");
        } else {
            ViewBag.PossibleCountries = countryRepository.All;
            return View();
        }
    }

    //
    // GET: /Address/Edit/5

    public ActionResult Edit(int id)
    {
        ViewBag.PossibleCountries = countryRepository.All;
        return View(addressRepository.Find(id));
    }

    //
    // POST: /Address/Edit/5

    [HttpPost]
    public ActionResult Edit(Address address)
    {
        if (ModelState.IsValid) {
            addressRepository.InsertOrUpdate(address);
            addressRepository.Save();
            return RedirectToAction("Index");
        } else {
            ViewBag.PossibleCountries = countryRepository.All;
            return View();
        }
    }

    //
    // GET: /Address/Delete/5

    public ActionResult Delete(int id)
    {
        return View(addressRepository.Find(id));
    }

    //
    // POST: /Address/Delete/5

    [HttpPost, ActionName("Delete")]
    public ActionResult DeleteConfirmed(int id)
    {
        addressRepository.Delete(id);
        addressRepository.Save();

        return RedirectToAction("Index");
    }
}

Контроллер страны

public class CountryController : Controller
{
    private readonly ICountryRepository countryRepository;

    // If you are using Dependency Injection, you can delete the following constructor
    public CountryController() : this(new CountryRepository())
    {
    }

    public CountryController(ICountryRepository countryRepository)
    {
        this.countryRepository = countryRepository;
    }

    //
    // GET: /Country/

    public ViewResult Index()
    {
        return View(countryRepository.All);
    }

    //
    // GET: /Country/Details/5

    public ViewResult Details(int id)
    {
        return View(countryRepository.Find(id));
    }

    //
    // GET: /Country/Create

    public ActionResult Create()
    {
        return View();
    } 

    //
    // POST: /Country/Create

    [HttpPost]
    public ActionResult Create(Country country)
    {
        if (ModelState.IsValid) {
            countryRepository.InsertOrUpdate(country);
            countryRepository.Save();
            return RedirectToAction("Index");
        } else {
            return View();
        }
    }

    //
    // GET: /Country/Edit/5

    public ActionResult Edit(int id)
    {
         return View(countryRepository.Find(id));
    }

    //
    // POST: /Country/Edit/5

    [HttpPost]
    public ActionResult Edit(Country country)
    {
        if (ModelState.IsValid) {
            countryRepository.InsertOrUpdate(country);
            countryRepository.Save();
            return RedirectToAction("Index");
        } else {
            return View();
        }
    }

    //
    // GET: /Country/Delete/5

    public ActionResult Delete(int id)
    {
        return View(countryRepository.Find(id));
    }

    //
    // POST: /Country/Delete/5

    [HttpPost, ActionName("Delete")]
    public ActionResult DeleteConfirmed(int id)
    {
        countryRepository.Delete(id);
        countryRepository.Save();

        return RedirectToAction("Index");
    }
}

Адрес хранилища

public class AddressRepository : IAddressRepository
{
    AddressTestContext context = new AddressTestContext();

    public IQueryable<Address> All
    {
        get { return context.Addresses; }
    }

    public IQueryable<Address> AllIncluding(params Expression<Func<Address, object>>[] includeProperties)
    {
        IQueryable<Address> query = context.Addresses;
        foreach (var includeProperty in includeProperties) {
            query = query.Include(includeProperty);
        }
        return query;
    }

    public Address Find(int id)
    {
        return context.Addresses.Find(id);
    }

    public void InsertOrUpdate(Address address)
    {
        if (address.ID == default(int)) {
            // New entity
            context.Addresses.Add(address);
        } else {
            // Existing entity
            address.CountryID = address.Country.ID;
            context.Entry(address).State = EntityState.Modified;
        }
    }

    public void Delete(int id)
    {
        var address = context.Addresses.Find(id);
        context.Addresses.Remove(address);
    }

    public void Save()
    {
        context.SaveChanges();
    }
}

public interface IAddressRepository
{
    IQueryable<Address> All { get; }
    IQueryable<Address> AllIncluding(params Expression<Func<Address, object>>[] includeProperties);
    Address Find(int id);
    void InsertOrUpdate(Address address);
    void Delete(int id);
    void Save();
}

Адрес CreateOrEdit.ascx View

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<AddressTest.Models.Address>" %>

<div class="editor-label">
    <%: Html.LabelFor(model => model.Street1) %>
</div>
<div class="editor-field">
    <%: Html.EditorFor(model => model.Street1) %>
    <%: Html.ValidationMessageFor(model => model.Street1) %>
</div>

<div class="editor-label">
    <%: Html.LabelFor(model => model.Street2) %>
</div>
<div class="editor-field">
    <%: Html.EditorFor(model => model.Street2) %>
    <%: Html.ValidationMessageFor(model => model.Street2) %>
</div>

<div class="editor-label">
    <%: Html.LabelFor(model => model.City) %>
</div>
<div class="editor-field">
    <%: Html.EditorFor(model => model.City) %>
    <%: Html.ValidationMessageFor(model => model.City) %>
</div>

<div class="editor-label">
    <%: Html.LabelFor(model => model.State) %>
</div>
<div class="editor-field">
    <%: Html.EditorFor(model => model.State) %>
    <%: Html.ValidationMessageFor(model => model.State) %>
</div>

<div class="editor-label">
    <%: Html.LabelFor(model => model.PostalCode) %>
</div>
<div class="editor-field">
    <%: Html.EditorFor(model => model.PostalCode) %>
    <%: Html.ValidationMessageFor(model => model.PostalCode) %>
</div>

<div class="editor-label">
    <%: Html.LabelFor(model => model.Country) %>
</div>
<div class="editor-field">
    <%: Html.DropDownListFor(model => model.Country.ID, ((IEnumerable<AddressTest.Models.Country>)ViewBag.PossibleCountries).Select(option => new SelectListItem {
        Text = (option == null ? "None" : option.Name), 
        Value = option.ID.ToString(),
        Selected = (Model != null) && (option.ID == Model.CountryID)
    }), "Choose...") %>
    <%: Html.ValidationMessageFor(model => model.Country.ID) %>
</div>

1 Ответ

1 голос
/ 23 июля 2011

Создать раскрывающийся список для скалярного свойства CountryID вместо Country.ID

<div class="editor-field">
    <%: Html.DropDownListFor(model => model.CountryID, new SelectList((IEnumerable<AddressTest.Models.Country>)ViewBag.PossibleCountries, "ID", "Name"), "Choose...") %>
    <%: Html.ValidationMessageFor(model => model.CountryID) %>
</div>

Я бы изменил Address POCO, чтобы сделать CountryID обнуляемым и применить Required атрибут

public class Address
{
    public int ID { get; set; }
    public string Street1 { get; set; }
    public string Street2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    [ForeignKey("Country")]
    [Required]
    public int? CountryID { get; set; }
    public Country Country { get; set; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...