Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Como injetar informações que não precisam ser definidas pelo usuário

Em uma View Create crio um novo registro e nele há dois atributos: Criador e DataDaCriacao.

Os dois são obtidos do próprio sistema: Id do usuário logado e a data de hoje.

Como faço para que eles sejam considerados no Bind?

Tenho o controller da Action Create assim:

public ActionResult Create()
        {

            ViewBag.TipoTarefaID = new CBMMSapp.DAO.TiposTarefaDAO().ListaParaDropDown();

            //Ao inves de apresentar uma lista, já carregar direto o usuario logado
            ViewBag.ApplicationUserId = User.Identity.GetUserId();
            ViewBag.Usuario = new CBMMSapp.DAO.UsuariosDAO().GetUser(User.Identity.GetUserId());

            //E a data de criação também será inserida automaticamente.
            ViewBag.DataCriacao = DateTime.Now;

            return View();
        }

        // POST: Tarefas/Create
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "ID,TipoTarefaID,Assunto,DataCriacao,ApplicationUserId")] Tarefa tarefa)
        {

            if (ModelState.IsValid)
            {
                db.Tarefas.Add(tarefa);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            ViewBag.TipoTarefaID = new CBMMSapp.DAO.TiposTarefaDAO().ListaParaDropDown( tarefa.TipoTarefaID);

            ViewBag.ApplicationUserId = User.Identity.GetUserId();

            ViewBag.DataCriacao = DateTime.Now;

            return View(tarefa);
        }

E na View Create tentei DisplayFor (mostrando o nome do usuário e a data) ou HiddenFor (para pelo menos ter a informação no submit) mas nada funcionou:

<div class="form-group">
            @Html.LabelFor(model => model.DataCriacao, "Data da Inserção" , htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DisplayFor(model => model.DataCriacao)
                @Html.HiddenFor(model => model.DataCriacao)                
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ApplicationUserId, "Criador", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DisplayFor(model => model.Usuario.Nome)
                @Html.HiddenFor(model => model.ApplicationUserId)
            </div>
        </div>

Quando a View Create é renderizada nenhum dos dois valores aparecem no DisplayFor

Nem as duas informações estão no resultado do Bind do ResultAction Create.

E quando o ModelState.IsValid() é aplicado, sempre falha e nenhuma mensagem de validação aparece na tela.

4 respostas

Olá, Jaqueline

Acho que você pode substituir essas duas linhas:

<span>@User.Identity.Name</span>
<input type="hidden" value=@User.Identity.Id/>

E como isso se identificaria com o termo "UserApplicationId" que é usado no Bind?

Tenho que usar um id?, ou um name?

    [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "ID,TipoTarefaID,Assunto,DataCriacao,ApplicationUserId,ClienteID")] Tarefa tarefa)
        {


            if (ModelState.IsValid)
            {
                db.Tarefas.Add(tarefa);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
solução!

Jaqueline, pelo que eu tinha entendido (me corrija se não for isso), o ID e nome do usuário e a data da criação são renderizados na view apenas para exibição e controle, e aparecem na View como somente-leitura. Assim, uma vez que o usuário submete o form, o servidor pode descartar essas informações (id do user, data da criação), porque o servidor já conhece essas informações. Pelo que entendo, você não precisa incluir esses campos no Bind, porque esses valores não são preenchidos no cliente. Como no seu primeiro código, você pode pegar esses valores diretamente no servidor, dentro da action:

            ViewBag.ApplicationUserId = User.Identity.GetUserId();

            ViewBag.DataCriacao = DateTime.Now;

Então eu recomendaria usar o Bind somente para os dados que o usuário vai preencher, e removeria o ApplicationUserId da lista, porque o servidor já tem essa informação, que é obtida através dos cookies de autenticação do ASP.NET Identity quando o usuário submete o form. É um dado a menos para você se preocupar.

Acho que não estou me fazendo entender. É justamente o contrário, não preciso elas mostradas na View, mas preciso que sejam gravadas quando o Create for executado.

Eu nem preciso que elas apareçam na renderização da View.

Mas quando for gravada uma Tarefa nova, ela tem essas duas informações, usuário e data atual que precisam ser gravadas.

Mas no Post Create isso já vem montado no Bind.

Então entendi que teria de inserir na View para que o Submit levasse para o Bind. E isso não estou conseguindo.

Como posso fazer o Create sem usar o Bind (que o scaffolding monta)?