Criei dois modelos. Um auxiliar de Cidades que chamei de xCidades e outro de Contatos que tem um atributo cidade:
public class xCidades
{
[Key]
public int CidadeId { get; set; }
[Required, StringLength(30)]
public string Cidade { get; set; }
[Required]
public xEstados Estado { get; set; }
}
public class Contatos
{
[Key]
public int ContatoId { get; set;}
[Required, StringLength(30)]
public string Contato { get; set;}
[StringLength(50)]
public string Endereco { get; set;}
[StringLength(30)]
public string Bairro { get; set; }
public int CidadeId { get; set;}
public xCidades Cidade { get; set; }
[StringLength(9)]
public string CEP { get; set;}
[Required, EmailAddress]
[DataType(DataType.EmailAddress)]
public string Email { get; set;}
[StringLength(15)]
[DataType(DataType.PhoneNumber)]
public string Fone_Celular { get; set;}
[StringLength(15)]
[DataType(DataType.PhoneNumber)]
public string Fone_Fixo { get; set;}
}
Com eles usei o Scaffold para gerar os controllers e views respectivos:
public class xCidadesController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
// GET: xCidades
public ActionResult Index()
{
return View(db.xCidades.ToList());
}
// GET: xCidades/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
xCidades xCidades = db.xCidades.Find(id);
if (xCidades == null)
{
return HttpNotFound();
}
return View(xCidades);
}
// GET: xCidades/Create
public ActionResult Create()
{
return View();
}
// POST: xCidades/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "CidadeId,Cidade,Estado")] xCidades xCidades)
{
if (ModelState.IsValid)
{
db.xCidades.Add(xCidades);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(xCidades);
}
// GET: xCidades/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
xCidades xCidades = db.xCidades.Find(id);
if (xCidades == null)
{
return HttpNotFound();
}
return View(xCidades);
}
// POST: xCidades/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "CidadeId,Cidade,Estado")] xCidades xCidades)
{
if (ModelState.IsValid)
{
db.Entry(xCidades).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(xCidades);
}
// GET: xCidades/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
xCidades xCidades = db.xCidades.Find(id);
if (xCidades == null)
{
return HttpNotFound();
}
return View(xCidades);
}
// POST: xCidades/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
xCidades xCidades = db.xCidades.Find(id);
db.xCidades.Remove(xCidades);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
public class ContatosController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
// GET: Contatos
public ActionResult Index()
{
var contatos = db.Contatos.Include(c => c.Cidade);
return View(contatos.ToList());
}
// GET: Contatos/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Contatos contatos = db.Contatos.Find(id);
if (contatos == null)
{
return HttpNotFound();
}
return View(contatos);
}
// GET: Contatos/Create
public ActionResult Create()
{
ViewBag.CidadeId = new SelectList(db.xCidades, "CidadeId", "Cidade");
return View();
}
// POST: Contatos/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ContatoId,Contato,Endereco,Bairro,CidadeId,CEP,Email,Fone_Celular,Fone_Fixo")] Contatos contatos)
{
if (ModelState.IsValid)
{
db.Contatos.Add(contatos);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CidadeId = new SelectList(db.xCidades, "CidadeId", "Cidade", contatos.CidadeId);
return View(contatos);
}
// GET: Contatos/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Contatos contatos = db.Contatos.Find(id);
if (contatos == null)
{
return HttpNotFound();
}
ViewBag.CidadeId = new SelectList(db.xCidades, "CidadeId", "Cidade", contatos.CidadeId);
return View(contatos);
}
// POST: Contatos/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ContatoId,Contato,Endereco,Bairro,CidadeId,CEP,Email,Fone_Celular,Fone_Fixo")] Contatos contatos)
{
if (ModelState.IsValid)
{
db.Entry(contatos).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CidadeId = new SelectList(db.xCidades, "CidadeId", "Cidade", contatos.CidadeId);
return View(contatos);
}
// GET: Contatos/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Contatos contatos = db.Contatos.Find(id);
if (contatos == null)
{
return HttpNotFound();
}
return View(contatos);
}
// POST: Contatos/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Contatos contatos = db.Contatos.Find(id);
db.Contatos.Remove(contatos);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
E as Views também foram geradas e funcionam perfeitamente na listagem (Index), Cadastro (Create) , Exclusão (Delete) e Alteração (Edit)
O único problema é que nas views de Detalhe (Details) e Exclusão (Delete) dos Contatos, o nome da Cidade não aparece. Em ambas, o nome da Cidade é um campo fixo.
Veja que na tela de listagem (Index) o nome da Cidade do contato também é um texto fixo e aparece perfeitamente.
Vou colocar as View Index (Que mostra o nome da Cidade) e a View Details (que não mostra)
@model IEnumerable<Projeto.Models.Contatos>
@{
ViewBag.Title = "Contatos";
}
<h2>Lista geral resumida</h2>
<p>
@Html.ActionLink("Criar novo contato", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Contato)
</th>
<!--th>
@Html.DisplayNameFor(model => model.Endereco)
</th>
<th>
@Html.DisplayNameFor(model => model.Bairro)
</th-->
<th>
@Html.DisplayNameFor(model => model.Cidade.Cidade)
</th>
<!--th>
@Html.DisplayNameFor(model => model.CEP)
</th-->
<th>
@Html.DisplayNameFor(model => model.Email)
</th>
<th>
@Html.DisplayNameFor(model => model.Fone_Celular)
</th>
<th>
@Html.DisplayNameFor(model => model.Fone_Fixo)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Contato)
</td>
<!--td>
@Html.DisplayFor(modelItem => item.Endereco)
</td>
<td>
@Html.DisplayFor(modelItem => item.Bairro)
</td-->
<td>
@Html.DisplayFor(modelItem => item.Cidade.Cidade)
</td>
<!--td>
@Html.DisplayFor(modelItem => item.CEP)
</td-->
<td>
@Html.DisplayFor(modelItem => item.Email)
</td>
<td>
@Html.DisplayFor(modelItem => item.Fone_Celular)
</td>
<td>
@Html.DisplayFor(modelItem => item.Fone_Fixo)
</td>
<td>
@Html.ActionLink("Alterar", "Edit", new { id=item.ContatoId }) |
@Html.ActionLink("Detalhes", "Details", new { id=item.ContatoId }) |
@Html.ActionLink("Excluir", "Delete", new { id=item.ContatoId })
</td>
</tr>
}
</table>
@model Projeto.Models.Contatos
@{
ViewBag.Title = "Contatos";
}
<h2>Detalhe</h2>
<div>
<h4>Contato</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Contato)
</dt>
<dd>
@Html.DisplayFor(model => model.Contato)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Endereco)
</dt>
<dd>
@Html.DisplayFor(model => model.Endereco)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Bairro)
</dt>
<dd>
@Html.DisplayFor(model => model.Bairro)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Cidade.Cidade)
</dt>
<dd>
@Html.DisplayFor(model => model.Cidade.Cidade)
</dd>
<dt>
@Html.DisplayNameFor(model => model.CEP)
</dt>
<dd>
@Html.DisplayFor(model => model.CEP)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Email)
</dt>
<dd>
@Html.DisplayFor(model => model.Email)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Fone_Celular)
</dt>
<dd>
@Html.DisplayFor(model => model.Fone_Celular)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Fone_Fixo)
</dt>
<dd>
@Html.DisplayFor(model => model.Fone_Fixo)
</dd>
</dl>
</div>
<p>
@Html.ActionLink("Alterar", "Edit", new { id = Model.ContatoId }) |
@Html.ActionLink("Voltar a lista resumo", "Index")
</p>