继承的类和剃刀 asp.net MVC 5



早上好,我在返回 View Razor 的数据库信息(使用 EF 6 代码优先方法生成(时遇到问题。问题是我想从视图中继承的类返回信息,但它们不可用,只显示基类的属性,而不是依赖类的属性。 以下是使用的模型、控制器和视图类:

类客户端模型

public class Client
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ClientId { get; set; }
[DataType(DataType.Date)]
public DateTime Birth { get; set; }
[Display(Name = "Telefone principal")]
public string Phone1 { get; set; }
[Display(Name = "Telefone Alternativo")]
public string Phone2 { get; set; }
public ICollection<OrcamentoContato> Contacts { get; set; }
public ICollection<Contrato> Contracts { get; set; }
}

类裂模型

public class PessoaFisica : Client
{
public TipoPessoa PersonType { get; set; }
[Required]
[Display(Name = "Nome completo*")]
[StringLength(250, ErrorMessage = "O campo é obrigatório.")]
public string Name { get; set; }
public string RG { get; set; }
[Required(ErrorMessage = "O campo CPF é obrigatório.")]
[StringLength(14)]
public string CPF { get; set; }
[Display(Name = "Filiação")]
public string Filiacao { get; set; }
[Display(Name = "Endereço")]
public string Address { get; set; }
}

类法学模型

public class PessoaJuridica : Client
{
public TipoPessoa PersonType { get; set; }
[Required]
[Display(Name = "Razão Social*")]
[StringLength(200, ErrorMessage = "O campo é obrigatório.")]
public string SocialName { get; set; }
[Required]
[Display(Name = "CNPJ*")]
[StringLength(200, ErrorMessage = "O campo é obrigatório.")]
public string CNPJ { get; set; }
[Display(Name = "Inscrição Estadual")]
public string InscricaoEstadual { get; set; }
[Display(Name = "Inscrição Municipal")]
public string InscricaoMunicipal { get; set; }
[Display(Name = "Endereço")]
public string Address { get; set; }
public string ContactWith { get; set; }
}

控制器

public ActionResult Index()
{            
var clients = db.Clients.ToList();
return View(clients);
}

索引视图

@model IEnumerable<CabinePhoto.Models.Entidades.Client>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Birth)
</th>
<th>
@Html.DisplayNameFor(model => model.Phone1)
</th>
<th>
@Html.DisplayNameFor(model => model.Phone2)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Birth)
</td>
<td>
@Html.DisplayFor(modelItem => item.Phone1)
</td>
<td>
@Html.DisplayFor(modelItem => item.Phone2)
</td>
</tr>
}

身份模型

public DbSet<Client> Clients { get; set; }
public DbSet<PessoaFisica> PessoaFisica { get; set; }
public DbSet<PessoaJuridica> PessoaJuridica { get; set; }

所有信息都存储在同一个客户端表中,因为我使用的是按层次结构继承的形式,但在视图中仅返回客户端模型信息

我已经能够解决这个问题。我将在这里记录我为解决继承问题所做的工作。

首先,我创建了一个 ViewModel 并放置了两个 ICollection 属性,我通过添加引用客户端表的查询来修改控制器,但专门带来了所需的类型,最后,我将 ViewModel 传递给 Index.cshtml,并使用两个 foreach 根据指定的类型从中检索信息,如下所示:

ClientesiewModel.cs

public class ClientesViewModel
{   
public IEnumerable<PessoaFisica> Fisica { get; set; }
public IEnumerable<PessoaJuridica> Juridica { get; set; }
}

控制.cs

public ActionResult Index()
{
var cliente_fisico = db.Clientes.OfType<PessoaFisica>().ToList();
var cliente_juridico = db.Clientes.OfType<PessoaJuridica>().ToList();
var cliente = db.Clientes.ToList();
ClientesViewModel clientes = new ClientesViewModel()
{
Fisica = cliente_fisico,
Juridica = cliente_juridico
};
return View(clientes);
}

View Index.cshtml

@model CabinePhoto.ViewModels.ClientesViewModel
<table class="table">
<tr>
<th>
@Html.DisplayName("Nome")
</th>
<th>
@Html.DisplayName("Telefone")
</th>
<th>
@Html.DisplayName("Telefone 2")
</th>
<th></th>
</tr>
@if (Model.Fisica != null || Model.Juridica != null)
{
foreach (var fisica in Model.Fisica)
{
<tr>
<td>
@Html.DisplayFor(modelItem => fisica.NomeCompleto)
</td>
<td>
@Html.DisplayFor(modelItem => fisica.TelefonePrincipal)
</td>
<td>
@Html.DisplayFor(modelItem => fisica.TelefoneAlternativo)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = fisica.ClienteId }) |
@Html.ActionLink("Details", "Details", new { id = fisica.ClienteId }) |
@Html.ActionLink("Delete", "Delete", new { id = fisica.ClienteId })
</td>
</tr>
}
foreach (var juridica in Model.Juridica)
{
<tr>
<td>
@Html.DisplayFor(modelItem => juridica.PessoaContato)
</td>
<td>
@Html.DisplayFor(modelItem => juridica.CNPJ)
</td>
<td>
@Html.DisplayFor(modelItem => juridica.TelefonePrincipal)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = juridica.ClienteId }) |
@Html.ActionLink("Details", "Details", new { id = juridica.ClienteId }) |
@Html.ActionLink("Delete", "Delete", new { id = juridica.ClienteId })
</td>
</tr>
}
}
</table>

感谢您之前分配的帮助

假设你的控制器中有这样的变量。

Client c = new Client();

如果你后来写

c.ClientId = 1;

它会完美地工作。

同样,如果你写

PessoaFisica p = new PessoaFisica ();

及以后

p.Name = "abc";

它也会起作用。

但是,如果你写

Client c = new PessoaFisica();
c.Name = "abc";

它将编译失败。

沿着同样的思路

@model IEnumerable <CabinePhoto.Models.Entidades.Client>

意味着Model的静态类型是Client对象的集合,它只允许您绑定到类Client定义的属性。

实体框架实际上返回正确的类型,但您实际上是通过要存储到的变量类型和视图的模型定义将所有内容向上转换为Client。本质上,您只需要转换为正确的类型。不幸的是,没有办法知道它被抛弃后应该是什么类型。您必须有条件地检查:

if (item is PessoaFisica)
{
var pessoaFiscica = (PessoaFisica)item;
// now you can access those derived typed properties off of `pessoaFiscica`
}

您还可以使用as并依赖于它在无法强制转换某些内容时返回 null 的事实:

var pessoaFiscica = item as PessoaFisica;
if (pessoaFiscica != null)
{
// access PessoaFiscica properties
}

在 C# 7.0 中,可以使用模式匹配语法稍微简化一下:

if (item is PessoaFiscica pessoaFiscica)
{
// use `pessoaFiscica`
}

模式匹配语法还允许您使用开关块,这可能会使您更轻松:

switch (item)
{
case PessoaFisica pessoaFisica:
// do something with `PessoaFisica` instance
break;
case PessoaJuridica pessoaJuridica:
// do something with `PessoaJuridica` instance
break;
default:
// do something with generic `Client` instance
break;
}

最新更新