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" )%>
Foi útil?

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; }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top