ASP.NET MVC 2 - Html.EditorPara um tipo anulável?
-
28-09-2020 - |
Pergunta
Eu tenho dois modelos de editor:um para decimal e outro para decimal?(anulável)
Mas quando tenho um decimal anulável no meu modelo, ele tenta carregar o editor decimal normal:
<%: Html.EditorFor(model => model.SomeDecimal )%>
<%: Html.EditorFor(model => model.SomeNullableDecimal )%>
O primeiro funciona bem e carrega o modelo do editor decimal.O segundo também tenta carregar o modelo decimal (e falha porque não é um campo decimal).
A mensagem de erro é:
The model item passed into the dictionary is null, but this dictionary requires
a non-null model item of type 'System.Decimal'.
Meus templates são declarados assim:
Modelo decimal:
<%@ Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<System.Decimal>" %>
Modelo decimal anulável:
<%@ Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<System.Decimal?>" %>
Eu sei que posso fazer funcionar passando o nome do modelo, por exemplo
Mas eu realmente preferiria que funcionasse automaticamente usando o tipo como todos os outros modelos.
<%: Html.EditorFor(model => model.SomeNullableDecimal,
"NullableDecimalTemplate" )%>
Solução
Obrigado a Bryan por adicionar uma recompensa para tentar obter uma solução positiva, mas terei que responder e dizer que descobri que a resposta é definitivamente NÃO - você não pode ter um modelo anulável descoberto automaticamente a partir de seu tipo.Você deve usar um nome de modelo.
Esta é a citação relevante do blog de Brad Wilson em http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html.Ele é uma fonte confiável em MVC, então tenho que acreditar nele quando ele diz:
Ao procurar o nome do tipo, o nome simples é usado (ou seja, tipo.name) sem espaço para nome.Além disso, se o tipo for anulável, procuramos t (para que você obtenha o modelo booleano, esteja usando "bool" ou "anulável")
Ele também continua dizendo
Isso significa que, se você estiver escrevendo modelos para tipos de valor, precisará explicar se o valor é anulado ou não.Você pode usar o Propriedade IsNullableValueType de ModelMetadata para determinar se o value é anulável.Veremos um exemplo disso abaixo com o modelo booleano embutido.
Então SIM, há uma resposta para esta pergunta, mas infelizmente a resposta é NÃO.
Para usar um modelo anulável, você deve usar explicitamente o nome do modelo:
<%: Html.EditorFor(model => model.SomeNullableDecimal, "NullableDecimalTemplate" )%>
Ou você pode usar um modelo que lide com o tipo anulável e não anulável:
<% if (ViewData.ModelMetadata.IsNullableValueType) { %>
<%= Html.DropDownList("", TriStateValues, new { @class = "list-box tri-state" })%>
<% } else { %>
<%= Html.CheckBox("", Value ?? false, new { @class = "check-box" })%>
<% } %>
Outras dicas
Para criar um modelo para um tipo anulável, nomeie seu modelo como o tipo de valor base e, em seguida, crie seu modelo de editor com um modelo anulável.
Por exemplo, quero fazer um modelo para int?.Criei um modelo de editor chamado "int32.cshtml" e estou usando int?como o modelo.
O modelo teria que ser denominado "Nullable`1".Como isso corresponderia a qualquer estrutura Nullable, você poderia alternar o tipo de modelo e renderizar o modelo parcial apropriado com base no tipo de "Nullable`1.ascx"
Não há como fazer da maneira que você deseja.Pode haver apenas um modelo para Decimal e Decimal?.Mas você pode determinar no modelo se o valor passado é do tipo anulável como este:
<% if (ViewData.ModelMetadata.IsNullableValueType) { %>
<%= Html.DropDownList("", TriStateValues, new { @class = "list-box tri-state" })%>
<% } else { %>
<%= Html.CheckBox("", Value ?? false, new { @class = "check-box" })%>
<% } %>
Para mais detalhes verifique esta postagem do blog
Sim, você pode fazer isso sem especificar o modelo em Html.EditorFor, mas então você precisa especificar o modelo em relação à propriedade anulável usando o atributo UIhint.
[UIHint("NullableDecimalTemplate")]
public decimal? SomeNullableDecimal { get; set; }