将多个模型组合成单一视图 - 创建问题

时间:2011-07-23 05:36:52

标签: entity-framework asp.net-mvc-3

我正在尝试将地址和国家/地区创建视图合并到一个视图中。我正在使用MVC 3和Repository Scaffolding& ASPX视图。我目前有一个已填充的国家/地区下拉列表,我正在尝试将其添加到地址创建视图中。我有编辑视图工作得很好。但是,当我尝试创建一个新地址时,即使我在下拉列表中选择了一个国家/地区,它也会添加一个空白名称的新国家/地区。我觉得我错过了一些非常基础的东西,因为这应该很容易。

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

<%@ 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 个答案:

答案 0 :(得分:1)

为标量属性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; }
}