quinta-feira, 13 de agosto de 2015

Bind com tipos nulos

Hoje pela manhã, ao acessar meus e-mails, havia um de um grupo do linkedin que eu sigo com uma postagem sobre problemas ao trabalhar com tipos anuláveis em ASP.NET MVC. Há algum tempo, pouco mais de dois meses passei por este mesmo problema. Um campo DateTime que era anulável, e quando eu tentava receber o valor através de um POST, o mesmo não aparecia no modelo.

Vamos a solução, imagine a seguinte classe:

public class Compras{
   public DateTime? Data { get; set;}
}
O controller que recebera o post tem a seguinte Action;

[HttpPost]
public ActionResult Salvar(Compras compras){
    //....
}

Ao realizar o post, a propriedade Data não conecta no objeto do tipo Compras criado pelo DefaultModelBinder (responsável por fazer a tradução da requisição HTTP para objetos complexos  compatíveis no .NET Framework) do ASP.MVC.

A solução é criar nosso próprio Binder, da seguinte maneira:

No seu projeto web crie uma classe implementando o interface IModelBinder que irá interceptar as requisições HTTP e detectar a propriedade anulável.
public class DateTimeBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        var modelState = new ModelState { Value = valueResult };
        object valorAtual = null;

        try
        {
            valorAtual = Convert.ToDateTime(valueResult.AttemptedValue, System.Globalization.CultureInfo.CurrentUICulture);
        }
        catch (FormatException e)
        {
            modelState.Errors.Add(e);
        }

        bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
        return valorAtual;
    }
}
No arquivo de projeto chamado Global.asax sobrescreva o método Init informando o novo binder, como segue:
public override void Init()
{
    base.Init();
    ModelBinders.Binders.Remove(typeof(DateTime));
    ModelBinders.Binders.Add(typeof(DateTime), new DateTimeBinder());
}
Desta forma agora você poder persistir suas propriedades anuláveis.
Você pode baixar um projeto de exemplo aqui no meu GitHub.
Segue link de referência: John Reilly

2 comentários:

  1. Boa iniciativa Charles. Desejo sucesso na sua caminhada.

    ResponderExcluir
    Respostas
    1. Obrigado Fernando, sempre que quiser, sinta-se a vontade para sugerir, criticar, opinar sobre os posts, sua contribuição é muito bem vinda

      Excluir