quinta-feira, 12 de setembro de 2013

Team Foundation Server Express 2012 - Parte 3/3

Nesta terceira parte daremos continuidade em nossa configuração básica para gerenciamento do nosso restaurante PacktDiner.

Criando o Product Backlog Items (PBIs)
A gerente Meeta quer que nos foquemos em dois PBIs, nomeados [Place Order] e [Calculate Bill]. Isto vai permitir ao garçom efetuar o pedido, usando o histórico de pedidos do usuário e calcular a conta mais tarde, usando o histórico do cálculo de conta do usuário.


Novamente no portal Web Access do TFS (acessado através do Team Explorer do Visual Studio), na área Home do portal, clique no botão [Product Backlog Item]



Preencha a tela conforme exemplificado abaixo



Crie outro PBI, chamado Calculate Bill



Associando PBI x Sprint
Deveremos agora associar um item de trabalho (o primeiro PBI para desenvolvimento) no primeiro Sprint. Para isto, no portal, clique no link [Work]



Expanda a opção [Shared Queries] e clique em [Product Backlog].



Neste ponto você pode visualizar os dois PBIs na lista da direita. Clique com o botão direito no PBI [Place Order] e mova a iteração para o Sprint Corrente (1-1)



Salve as alterações



Se você se deparar com o erro da tela abaixo (TF51011) você terá que manualmente alterar todas as referências ao Sprint com o nome errado, alterando corretamente, salvando e rodando a query para resolver este "bug" do produto, conforme exemplifica a tela abaixo. Não se esqueça de alterar em todos os itens (dentro de Shared Queries -> Current Sprint)



Criando Sub-Tarefas
Cada PBI deve ser desmembrado em tarefas, pois os desenvolvedores irão trabalhar com tarefas. Para isto, acesse a opção [New -> Task] da área [Work] do portal



E cadastre uma nova tarefa para a [Sprint 1-1] da forma mostrada abaixo



Salve e crie mais duas, com os mesmos dados, mas com os nomes [Implement Business Logic] e [Implement Storage Service]
Após estes passos crie outra tarefa chamada [Add test cases] com o campo Activity como [Requirements].



Configurando a estrutura Source Control
Isto se faz no Visual Studio. Voltando ao Team Explorer, selecione a opção Home, depois o link [Source Control Explorer] abaixo do nó [Pending Changes].



Precisamos associar nossa estrutura de fontes a um diretório físico em nossa máquina. Clique no link [Not mapped] para isto, e associe a um diretório de sua escolha (por exemplo d:\projetos\PacktDiner)



Clicando no botão [Map] você receberá a pergunta abaixo. Responda [Não] a esta pergunta



Agora sim clique no botão [New Folder]. Crie a estrutura exatamente como ilustrado abaixo



Depois clique em Pending Changes, no Team Explorer





Agora realize o Check In, adicionando um comentário, por exemplo, "pastas adicionadas" e clique no botão [Check In]



Criando a aplicação WaiterApp no Visual Studio
Até o momento criamos a estrutura da aplicação no TFS e o mapeamento em um diretório físico na nossa máquina (no meu caso D:\Projetos\PacktDiner\WaiterApp\main). Porém este diretório está vazio certo. Não existe uma aplicação lá dentro. Vamos rapidamente criar, usando o Template do Visual Studio para aplicações ASP.NET MVC, por exemplo.

No Visual Studio escolha a opção de Menu File -> New -> Project. Note na imagem abaixo que devemos criar o projeto dentro da pasta [src].






Pronto. Não vamos, é claro, criar telas e regras de negócio para atender a aplicação do restautante, pois o objetivo deste artigo é controlar a aplicação no TFS.

Agora precisamos adicionar todos os arquivos criados na pasta [src] ao TFS, pelo Visual Studio. Na janela [Source Control Explorer] pressione [Add Files to Source Control]







Na janela Team Explorer, sob a aba Home, Pressione o link Pending Changes e adicione um comentário apropriado (Waiter App adicionada, por exemplo) e clique no botão Check In.

E como passo final, feche a solução, dê duplo clique no nome da solução [WaiterApp.sln] no Source Control Explorer e crie o link da sua solução no Source Control.

Clique Sim



Selecione uma linha por vez e clique no botão [bind] para criar a conexão



Clique em Check Out para começar a trabalhar nos arquivos



Instalando e configurando o sistema de BUILD
Falta agora apontar nossa aplicação a um processo automático de Build. Normalmente se aponta o projeto para um servidor separado de Build. Mas para nosso tutorial criaremos este processo no mesmo servidor do TFS.
Para isto, inicie novamente o [Setup] de instalação do TFS (VS2012.3 TFS Express enu.iso).



Escolha a opção [Configure Team Foundation Build Service]





Botão Next



Botão Next











Integração contínua de BUILD
Vamos trabalhar agora com este processo de Build no Visual Studio. Entre no [Team Explorer - Build]



Clique em [New Build Definition] e preencha de acordo com as telas de exemplo





Para a configuração de [Source Settings] altere esta aba exatamente conforme mostrado abaixo



No próximo passo (Build Defaults) crie na sua máquina um diretório chamado [Drops]



Torne este diretório [compartilhado]





Atente para o fato de que a conta a qual o serviço de build está rodando possua permissão na pasta Drops (conta [Network Service]). Adicione o caminho do diretório compartilhado no campo [Stating Location]



E por último, o Process Build



Salve a definição de Build



Botão direito no Build criado e escolha [Queue a new build]





Pronto. Agora faça uma alteração em algum arquivo, depois efetue o Check-In, o qual será levado para a aba de Pending Changes. Adicione um comentário e conclua o Check-In. Vá para a aba Builds e note que um novo Build foi inicialdo automaticamente. Após um pequeno processo de espera, o processo termina (muda para verde) indicando um Build bem sucedido.





E eis que surge no diretório Drops sua aplicação automaticamente compilada e pronta para ser implantada em produção!

Team Foundation Server Express 2012 - Parte 2/3

Dando continuidade ao artigo anterior sobre TFS, vamos agora criar nosso primeiro projeto. O projeto tem como objetivo disponibilizar uma aplicação para os garçons de um restaurante (Packt Diner) de forma a automatizar o processo de ordens de pedido e pagamentos. Chamaremos a aplicação de WaiterApp. Para o projeto teremos dois desenvolvedores no time, Jakob e Terje, e um gerente de projeto, Meeta.


Encontrando e conectando nosso TFS Server 2012

Após a instalação do TFS Server, nos é fornecida uma URL para acesso e conexão. Se não lembramos esta URL, podemos abrir o Console do TFS para recuperar esta informação, indo em [Todos os Programas -> Microsoft Visual Studio Team Foundation Server 2012].




Abaixo de [Application Tier] selecione [Team Project Collections] e note a URL para DefaultCollection.
Abra agora o Visual Studio 2012 e habilite-o para usar o TFS (Tools -> Options -> Source Control -> Current Source Control Plugin).
Depois acesse o Menu [Team] e selecione [Connect To Team Foundation Server].
Na área [Team Explorer] clique no link [Connect]. Na tela de conexão, selecione o nome no servidor TFS. Vai notar que este assistente já vai trazer o nome do computador local. É o que precisamos no momento. Selecione esta opção e clique no botão [Connect].



Criando o Team Project
No Team Explorer, clique no nome [Home] para abrir um Menu de opções. Clique na opção [Projects And My Teams -> New Team Project]



Agora preencha as próximas telas conforme exemplos abaixo:







Criando o Team
Como próximo nível, precisamos criar a Equipe que vai trabalhar neste projeto (Jakob, Terje e Meeta). Faremos isto através do link [Web Access] presente no Team Explorer do Visual Studio.



Com o portal do TFS aberto, clique em [Manage All Members] e adicione os três membros que citei acima.



Só tem um pequeno problema, sua máquina não possui os usuários (Jakob, Terje e Meeta). Portanto, crie-os no seu Windows, através do Control Panel -> User Accounts -> Manage Users Accounts, e adicione-os.



Obs: Lembrando que na tela do portal do TFS você deve digitar o nome do usuário que criou no seu Windows, mesmo se não for encontrado pelo [picklist] ao qual está digitando, pois você pode adicionar usuários que não pertencem ao [domínio] em que se encontra atualmente.



Estrutuando as Áreas para Categorização e Plano de Release
Chegou o momento de definição das áreas - que é a categorização de nosso trabalho - associando uma área para o nível mais superior (para a aplicação em si que estamos fazendo) e duas sub-áreas, na qual a gerente Meeta quer que desenvolvamos, chamada [Ordering - Pedido] e [Payment]. Ela também quer dois releases do produto, o que faremos no recurso chamado [iteration].

Desta forma, novamente na tela Web Access do TFS, criaremos primeiro nossas Áreas, clicando no link [Configure work areas...]



Adicione uma área filha chamada WaiterApp, a qual será o nome de nossa aplicação. Abaixo disto, adicione mais duas áreas filhas chamadas Ordering e Payment.

Desmarque o checkbox padrão, não se preocupando com a mensagem de "erro" que aparecerá. Na sequência, marque o checkbox para WaiterApp. Agora esta aplicação se torna a área padrão.



Agora devemos configurar o plano de Release da aplicação. Feche a tela de Áreas e clque na opção [Configure Schedule and Iterations] da página principal do portal



Vamos agora preparar o plano para múltiplas aplicações, adicionando um novo filho abaixo do nó raiz, nomeando como WaiterApp.
Referente a nossa estratégia de release, temos duas opções
1 - Fazer como que todos os desenvolvimentos sigam a mesma agenda, usando neste caso o padrão Microsoft.
2 - Deixar que cada desenvolvimento tenha sua própria agenda. Neste caso, siga nosso exemplo e adicione os nomes das aplicações abaixo da pasta raiz.
Clique e arraste os itens [Release 1] e [Release 2] para dentro do item [WaiterApp]

Exclua as outras Releases (botão direito no item para excluir) e Sprints desnecessárias, e deixe nossa tela de Iterations exatamente como abaixo:



Referente as datas dos Sprints, você pode colocar a sua, com um intervalo de 2 semanas, como sugestão.

Também mude a opção de Backlog para o item [WaiterApp]



Na terceira parte deste artigo daremos continuidade nas configurações básicas do nosso projeto.

[]s

Team Foundation Server Express 2012 - Parte 1/3

Em substituição ao "velho" Visual Source Source, podemos dizer que o TFS é mais uma Plataforma de Gerenciamento de Projetos do que apenas uma ferramenta de versionamento de códigos.
Ela pode ser configurada, adaptada e extendida para se adequar as suas necessidades em um grau elevado.
Inciaremos neste artigo com a instalação da versão Express 2012 do produto, que nos permite utilizar muitos recursos interessantes, de forma que aprenderemos:

- Version Control
Que se refere aos fundamentos deste controle, o uso de ChangeSets, CheckIns e History
Como recuperar Versions, Annotations, Labels
Como criar um Branch e Merge do nosso código

- Work Items
Os fundamentos deste Item de Trabalho e como usá-los
Como criar Work Items
Querying Work Items
Transferir Work Items para outras ferramentas, como Excel

- Build
Indispensável! Veremos como usar
Também como Monitorar

Sendo o TFS a mais nova versão da Microsoft em sistemas de ALM (Application Lifecycle Management) ela tem portanto o objetivo de governar todo este aspecto de desenvolvimento de software, incluindo o gerenciamento de requerimentos, de projetos, desenvolvimento, testes e implantação com qualidade.

Um outro aspecto importante é que esta plataforma pode ser acessada de diversas formas, por exemplo, pelo Agile Web Access, Visual Studio, Office, etc.

A imagem abaixo mostra isto de forma clara:



Pensar no fato de que podemos integrar, através desta ferramenta, todos os envolvidos no projeto, deste o solicitante de uma tarefa (usando por exemplo a ferramenta Agile Web Access), que passa pelo arquiteto e gerente do projeto (podendo usar o Excel)que por sua vez repassa a tarefa para um desenvolvedor (recebendo a tarefa diretamente no Visual Studio) e que, ao compilar e efetuar um CheckIn o Sistema de Build do TFS pode detectar isto e inicial o processo automático de Build da aplicação para testes finais, parece um cenário excelente!...

Mas falando em instalação, apesar das diversar formas existentes, usaremos neste artigo a Básica, até porque estamos usando a versão Express do produto. Na versão paga existe ainda a forma de instalação [Standard/Advanced] que utiliza os recursos adicionais como SQL Reporting Services para relatórios, SQL analylis Services para uso de DataWareHouse e Sharepoint Foundation para uso de Portal. Existe ainda uma outra forma de instalação, que na verdade já está instalada, que é a versão TFS Azure, servida pela Microsoft.

Instalação Básica
É a instalação em um computador local, podendo ser instalada em um Windows 7 ou 8; também em um Windows Server 2008 ou superior.
Para tanto, comece efetuando o download do instalador. Neste link podemos executar e ou baixar uma ISO de instalação. Com a iso preparada, rode o arquivo tfs_express.exe.







Após reiniciar a máquina, a tela de Configuration Center aparece para auxiliar-nos na instalação final do produto, juntamente com:
- a instalação do SQL Express 2012 - se não existir;
- existindo uma versão anterior o wizard efetuará um Upgrade
- ou usando uma instalação paga existente (2008 R2 ou 2012)







Se você se deparar com o erro abaixo, na qual falhou o upgrade do SQL Express para 2012, terá que efetuar o Upgrade [Manual] do SQL Express e voltar a instalar o TFS.



Para efetuar o Upgrade para o SQL Express 2012
- Primeiro instale o SQL Server 2008 Service Pack 3
- E siga os passos deste blog

Voltando a nossa instalação do TFS





No console do TFS podemos revisar a instalação e efetuar diversas alterações:



No próximo artigo criaremos nosso primeiro projeto pelo TFS - Parte 2/3

Ref: Team Foundation Server 2012 Starter, by Jakob Ehn / Terje Sandrstron - Packt Publishing

[]s

segunda-feira, 9 de setembro de 2013

ASP.NET MVC 4 - Upload e Visualização de Imagens

Neste artigo veremos como o processo de manipulação de imagens no ASP.NET MVC se tornou mais simples. Neste tutorial, faremos o seguinte:
1 - Criaremos um projeto ASP.NET MVC 4 e adicionaremos um banco de dados local, via EntityFramework, com uma tabela para armazenar os dados da imagem na qual efetuaremos o Upload
2 - Atualizaremos a interface MVC para efetuar o Upload de um arquivo
3 - Criaremos um mecanismo para visualizar a imagem que foi inserida no nosso banco de dados local

BAIXE OS FONTES (EM .NET CORE): ASP.NET MVC CORE - Image Upload


1 - Projeto com a tabela de Imagens

Crie um novo projeto no VS 2012, conforme imagens abaixo:



Adicione uma classe chamada [Imagem.cs] dentro da pasta [Models] do projeto criado, com o seguinte conteúdo:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;

namespace MvcApplication2.Models
{
    public class Imagem
    {
        public static int _inc;
        public int Id { get; set; }
        public string Nome { get; set; }
        public string Conteudo { get; set; }
        public string Tipo { get; set; }
        public int Tamanho { get; set; }

        public Imagem() {
            Id = Interlocked.Increment(ref _inc);
        }
    }
}

Compile o projeto, e depois adicione uma classe controladora chamada [ImagemController] dentro da pasta [Controllers] do projeto, da forma que vemos nas imagens abaixo:



Neste ponto já temos nosso cadastro pronto. Vamos adicionar o objeto de Upload de imagens nas telas [Create.cshtml e Edit.cshtml].

2 - Atualização da Create.cshtml

Atualize conteúdo da View Create.cshtml por todo código abaixo:


@model MvcApplication2.Models.Imagem

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

<script src="~/Scripts/jquery-1.8.2.js" type="text/javascript"></script>

<script type="text/javascript">

    $(document).ready(function () {
        $("#divFileUpload").mouseenter(function () {
            imageStatusOnHover();
        }).mouseleave(function(){ 
            imageStatusOffHover();
        });

    });

    function imageStatusOnHover() {
        if ($("#file1").val() != "") {
            var fileURL = $("#file1").val().replace(/\\/g, "\\\\");
            showImagemTooltip(fileURL);
        }
    }

    function imageStatusOffHover() {
        $('#divImageTooltip').hide();
    }

    function showImagemTooltip(file) {
        $('#divImageTooltip').css({
            "backgroundImage": "url(" + file + ")",
            "background-repeat": "no-repeat",
            "background-size": "contain",
            "background-position": "center",
            "background-color": "white"
        });

        $('#divImageTooltip').show();
        $("#divFileUpload").mousemove(function (event) {
            $('#divImageTooltip').css({ 'top': event.pageY, 'left': event.pageX });
        });
    }


</script>

@using (Html.BeginForm("Create", "Imagem", FormMethod.Post, new { enctype = "multipart/form-data" })) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Imagem</legend>

        <table>
            <tr>
                <td>
                    <div id="divFileUpload">
                        <input type="file" id="file1" name="file1" />
                    </div>
                </td>
            </tr>
            <tr>
                <td>
                    <div id="divImageTooltip" style="display:none; position: absolute; height:200px; width:200px; border:solid 1px black;"></div>
                </td>                
            </tr>
        </table>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Desta forma, executando a aplicação, adicionando a URL "/Imagem" e clicando no botão [Create New], poderá já testar o recurso de Upload e Visualização de uma imagem [ao passar o mouse sobre o objeto de Upload], conforme mostra a tela abaixo:



Agora precisamos criar um processo para salvar/visualizar a imagem no nosso banco de dados.

3 - Salvar e Visualizar a Imagem do Banco de Dados

Altere todo conteúdo do seu arquivo [Index.cshtml] pelo especificado abaixo:


@model IEnumerable<MvcApplication2.Models.Imagem>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Nome)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Tipo)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Tamanho)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Nome)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Tipo)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Tamanho)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
            @Html.ActionLink("Details", "Details", new { id=item.Id }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.Id })
        </td>
    </tr>
}

</table>


Altere todo o conteúdo do arquivo [Edit.cshtml] pelo conteúdo abaixo:


@model MvcApplication2.Models.Imagem

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

<script src="~/Scripts/jquery-1.8.2.js" type="text/javascript"></script>

<script type="text/javascript">

    $(document).ready(function () {
        $("#divFileUpload").mouseenter(function () {
            imageStatusOnHover();
        }).mouseleave(function(){ 
            imageStatusOffHover();
        });

    });

    function imageStatusOnHover() {
        var fileTitleContent = $("#fileTitle1")[0].textContent;
        if (fileTitleContent != "")
        {
            var url = String(window.location.protocol) + "//" + String(window.location.host) + "/";
            url += "Imagem/BuscarAnexoImagemPorNome?nomeImagem=" + fileTitleContent;

            $.ajax({
                type: "POST",
                url: url,
                success: function (file) {
                    showImagemTooltip(file);
                }
            });
        }
    }

    function imageStatusOffHover() {
        $('#divImageTooltip').hide();
    }

    function showImagemTooltip(file) {
        $('#divImageTooltip').css({
            "backgroundImage": "url(" + file.Url + ")",
            "background-repeat": "no-repeat",
            "background-size": "contain",
            "background-position": "center",
            "background-color": "white"
        });

        $('#divImageTooltip').show();
        $("#divFileUpload").mousemove(function (event) {
            $('#divImageTooltip').css({ 'top': event.pageY, 'left': event.pageX });
        });
    }


</script>

@using (Html.BeginForm("Edit", "Imagem", FormMethod.Post, new { enctype = "multipart/form-data" }))
{

    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Imagem</legend>

        <table>
            <tr>
                <td>
                    <div id="divFileUpload">
                        <label id="fileTitle1">@ViewBag.FileTitleLabel</label>
                        <input type="file" id="file1" name="file1" />
                    </div>
                </td>
            </tr>
            <tr>
                <td>
                    <div id="divImageTooltip" style="display:none; position: absolute; height:200px; width:200px; border:solid 1px black;"></div>
                </td>                
            </tr>
        </table>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}


E finalmente, altere também todo conteúdo da classe [ImagemController.cs] pelo especificado abaixo.
Obs: Como o objetivo é mostrar apenas os recursos de imagem, não me preocupei em separar o projeto em camadas, pois vai notar que o acesso a dados ficou na classe controladora.


using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication2.Models;

namespace MvcApplication2.Controllers
{
    public class ImagemController : Controller
    {
        private StoreDBContext db = new StoreDBContext();

        //
        // GET: /Imagem/

        public ActionResult Index()
        {
            return View(db.Imagems.ToList());
        }

        //
        // GET: /Imagem/Details/5

        public ActionResult Details(int id = 0)
        {
            Imagem imagem = db.Imagems.Find(id);
            if (imagem == null)
            {
                return HttpNotFound();
            }
            return View(imagem);
        }

        //
        // GET: /Imagem/Create

        public ActionResult Create()
        {
            return View();
        }

        //
        // POST: /Imagem/Create

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(Imagem imagem)
        {
            var img = new Imagem();
            var file1 = Request.Files["file1"];

            if (!string.IsNullOrEmpty(file1.FileName))
            {
                img.Nome = file1.FileName.Substring(file1.FileName.LastIndexOf("\\") + 1);

                var binaryData = new Byte[file1.InputStream.Length];
                file1.InputStream.Read(binaryData, 0, (int)file1.InputStream.Length);
                var base64String = Convert.ToBase64String(binaryData, 0, binaryData.Length);
                img.Conteudo = base64String;

                img.Tamanho = file1.ContentLength;
                img.Tipo = file1.ContentType;

                db.Imagems.Add(img);
                db.SaveChanges();
            }

            return RedirectToAction("Index");
        }

        //
        // GET: /Imagem/Edit/5

        public ActionResult Edit(int id = 0)
        {
            Imagem imagem = db.Imagems.Find(id);

            ViewBag.FileTitleLabel = "";
            if (imagem != null) ViewBag.FileTitleLabel = imagem.Nome;

            return View(imagem);
        }

        //
        // POST: /Imagem/Edit/5

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(Imagem imagem)
        {

            ViewBag.FileTitleLabel = "";

            return RedirectToAction("Index");
        }

        //
        // GET: /Imagem/Delete/5

        public ActionResult Delete(int id = 0)
        {
            Imagem imagem = db.Imagems.Find(id);
            if (imagem == null)
            {
                return HttpNotFound();
            }
            return View(imagem);
        }

        //
        // POST: /Imagem/Delete/5

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Imagem imagem = db.Imagems.Find(id);
            db.Imagems.Remove(imagem);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        public ActionResult BuscarAnexoImagemPorNome(string nomeImagem)
        {
            return Json(new { Url = Url.Action("CriarAnexoImagem", "Imagem", new { nomeImagem = nomeImagem }) });
        }

        public FileContentResult CriarAnexoImagem(string nomeImagem)
        {
            var file = db.Imagems.Where(w => w.Nome.Equals(nomeImagem));
            if (file == null) return null;

            return File(Convert.FromBase64String(file.FirstOrDefault().Conteudo), file.FirstOrDefault().Tipo, file.FirstOrDefault().Nome);
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}


Nesta classe controladora, e no arquivo Edit.cshtml, vai notar pontos interessantes:
- Ao passar o mouse sobre o objeto de Upload de arquivos, ocorre uma chamada Ajax para executar o método [Imagem/BuscarAnexoImagemPorNome]
- Este método busca o registro da imagem e retorna um JSON com a chamada para outro método [CriarAnexoImagem] que vai retornar o arquivo (FileContentResult), através da conversão da String que foi salva no formato [Base64] no banco de dados (na Action Create)
- Depois o JScript [showImagemTooltip] mostra a imagem em um Div, tendo como background a imagem retornada.

Em fim, sua tela de consulta deverá estar como exemplificado abaixo:



[]s

terça-feira, 3 de setembro de 2013

ASP.NET MVC 4 - EF Data Migration

A quantidade de recursos para desenvolvimento Web usando o Microsoft ASP.NET MVC 4 é realmente grande. Falando um pouco destes recursos, existe um que surgiu, a partir da versão 4.3 do EntityFramework, que se chama Data Migration.
Com este recurso podemos unir o poder da codificação .NET com Scripts de banco de dados!

Por exemplo, imagine o cenário onde:
1 - Criaremos uma classe que representará o modelo de uma tabela de Produtos e baseado neste modelo usaremos o EntityFramework para gerar um Banco de Dados com esta tabela
2 - Habilitaremos o recurso de Data-Migration no VS 2012
3 - Efetuaremos alterações nesta tabela, usando o recurso Data-Migration
4 - Criaremos um Script de Banco de Dados, através do Data-Migration

Vamos começar:

1 - Criar a classe de Produtos
Abra o VS 2012 e crie um novo projeto ASP.NET MVC 4, com o template [Internet Application], conforme ilustram as figuras abaixo:


Com o projeto criado, adicione una classe chamada Product.cs, dentro do diretório [Models]. Segue conteúdo da classe:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcApplication1.Models
{
    public class Product
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
}

Importante: Neste ponto COMPILE a solução para que esta classe fique visível ao controladores.
Agora vamos criar nosso Controller do ASP.NET MVC; dentro da pasta [Controllers] adicione um controlador chamado "ProductsController", de acordo com a imagem abaixo: 





Importante: Note a opção [Data Context Class]; Neste momento vamos criar uma NOVA, para justamente começarmos a nos beneficiar do recurso do EntityFramework. Escolha, portanto, a opção [New Data Context]. Uma nova janela aparecerá para nomearmos nosso EF. Renomeie conforme ilustra a imagem abaixo: 




Clique no botão [Ok] depois em [Add] na tela principal para criarmos nosso Controller.
Neste momento teremos na nossa solução do VS toda a estrutura pronta para nosso cadastro de produtos, conforme ilustra a imagem: 



Tanto que neste ponto, podemos executar a aplicação e adicionar a URL do browser "/Products" e ver que temos um cadastro funcional. Mas o que nos interessa vem agora, que é a utilização do Data-Migration para gerarmos um Script de banco de dados da tabela de produtos.

Note que no momento em que você criou a classe StoreDBContext.cs, o VS criou um banco de dados para lhe apoiar neste processo. Veja como localizá-lo:
- Entre no Web.config da solução, procure pela palavra [StoreDBContext] e notará que foi criada uma ConnectionString que aponta para um [Data Source]. No meu caso, está apontando para [(localdb)\v11.0].
- Entre no [Server Explorer] do VS e EXCLUA todos os itens da opção [Data Connections]
- Adicione uma nova conexão configurada conforme a imagem:



Também perceba que escolho um banco de dados já existente, chamado [StoreDBContext-20130903153401]
Com isto, seu server explorer agora mostra a tabela de Produtos que você criou somente como uma Classe no seu projeto:



2 - Habilitar o Data-Migration
Como utilizaremos o VS 2012, já temos a disposição a versão mais nova do EntityFramework, a 4.5, onde usaremos o recurso do Data-Migration. Para tanto, clique no Menu Tools -> Library Package Manager -> Package Manager Console
Com o console visível, digite:

Enable-Migrations -ContextTypeName MvcApplication1.Models.StoreDBContext

Com isto, note que foi criado na solução do VS uma pasta chamada [Migrations] com sua primeira versão do [code-based Migration - 201309031854591_InitialCreate.cs].
Sua console/VS deverá estar como ilustra as imagens:




Depois analise com calma a classe [*_InitialCreate.cs] e perceba que existe um código pronto para suporte de geração de Script de Migração.

3 - Alteração da classe de Produtos
Em um processo real, as alterações no modelo de uma tabela virão com frequência. Portanto, como nos baseamos sempre na alteração da classe que representa a tabela, vamos adicionar uma campo chamado [Price] na classe e alterar o Banco de Dados usando o Data-Migration.
Adicione a seguinte propriedade na classe Products.cs :

   public decimal Price { get; set; }

Salve a classe e digite, no Package Manager Console:

   Add-Migration AddProductsPrice

O nome [AddProductsPrice] é livre, você adiciona o que desejar. Como resultado vai notar que na pasta [Migrations] do VS existirá agora o arquivo [201309031931456_AddProductsPrice.cs] que reflete a alteração do novo campo criado.

Digite agora no console:

Update-Database

E vai notar no [Server Explorer] que o VS alterou a estrutura da tabela de Produtos.

4 - Criar o Script de Banco de Dados pelo Data-Migration
Como processo final vamos gerar o Script, digitando no console:

   Update-Database -Script -SourceMigration: $InitialDatabase

Pronto! O VS criou o Script para ser executado no Sql Server por um DBA.



Abraços!

Refs:
Automatic Code First Migrations
Code First Migrations