Visual Studio

Desenvolvimento colaborativo em tempo real com Live Share

Ferramentas de desenvolvimento colaborativo em tempo real são de grande ajuda para times que trabalham remoto. Nesse artigo vamos conhecer a extensão Live Share do Visual Studio Code e Visual Studio, aprenderemos como instalar e utilizar seus recursos para programar em conjunto com uma ou mais pessoas.

Como funciona o desenvolvimento colaborativo em tempo real com a extensão Live Share

A extensão Live Share permite aos participantes da sessão visualizar ou editar o projeto no qual o grupo está trabalhando. Isso é feito diretamente dentro do Visual Studio. Não é necessário nenhuma ferramenta de acesso remoto, compartilhamento de janelas do sistema operacional ou ferramenta de comunicação.

A extensão Live Share também deixa compartilhar facilmente servidores disponíveis na máquina onde o projeto está rodando, com isso é possível compartilhar serviços da aplicação ou banco de dados de forma simples. Ela também possui a possibilidade de compartilhar acesso a terminais da máquina.

React - Introdução
Curso de React - Introdução
CONHEÇA O CURSO

Como instalar a extensão Live Share para desenvolvimento colaborativo

A ferramenta Live Share é composta por 3 extensões do Visual Studio Code:

  • Live Share – Possibilita a criação da sessão e o compartilhamento do código do projeto, servidores e terminal;
  • Live Share Audio – Permite conversar via áudio entre os membros da sessão;
  • Live Share Chat – Permite conversar via chat com os membros da sessão.

É possível instalar cada uma delas separadamente de acordo com os recursos que for utilizar, porém existe uma extensão chamada Live Share Extension Pack que já instala as 3 de uma única vez, caso for utilizar todas as funções.

No Visual Studio Code para instalar, basta Abrir o Editor, ir no gerenciador de extensões no canto esquerdo ou usando atalho (Ctrl + Shift + X). Depois basta procurar por Live Share que verá todas as extensões comentadas acima, basta escolher qual deseja e instalar:

Painel de instalação do Visual Studio Code mostrando a extensão Live Share para desenvolvimento colaborativo em tempo real

No Visual Studio 2019 a Live Share já vem por padrão. Já no 2017 é necessário instalar a extensão Live Share para Visual Studio listada no marketplace.

Iniciando a primeira sessão desenvolvimento colaborativo em tempo real

No post vamos mostrar os exemplos usando o Visual Studio Code, mas a lógica é a mesma que no Visual Studio.

Após instalar a extensão um novo item será criado no menu do Visual Studio Code referente à extensão:

Painel da extensão live share para inicio de sessão de desenvolvimento colaborativo em tempo real

Na extensão temos as seguintes opções de cima para baixo:

  • Juntar-se a uma sessão de colaboração – Possibilita conectar a uma sessão existente criada por outro usuário;
  • Iniciar uma sessão de colaboração – Permite criar uma nova sessão;
  • Iniciar uma sessão somente leitura de colaboração – Permite criar uma nova sessão de colaboração, porém os membros não poderão modificar o código do projeto.

Se você for convidado para participar de uma sessão existente, quem criou a sessão deverá te passar um link com endereço dela, basta clicar sobre ele e o navegador já abrirá uma nova janela do editor e entrará na sessão. Caso você seja o criador da sessão, precisa compartilhar o link de acesso com as outras pessoas que deseja convidar.

O serviço e a extensão Live Share são mantidos para Microsoft. A utilização não possui nenhum custo, porém é necessário ter uma conta da Microsoft ou do Github para conseguir utilizar. Assim que tentar entrar em uma sessão ou iniciar, ele abrirá o navegador para logar em uma dessas contas e dar acesso ao serviço.

Participando de uma sessão de desenvolvimento em equipe online

Uma vez conectado na sessão, se for convidado poderá navegar e visualizar os arquivos do projeto normalmente como se fosse um projeto local. Dependendo da sua permissão também poderá editar os arquivos do projeto:

Edição do projeto remoto para trabalho online em equipe com a extensão live share

Note em amarelo após a palavra treinaweb um ponteiro de edição amarelo. Ele indica que outro usuário está com ponteiro atualmente nesse local. Conforme cada usuário for adicionando ou removendo código é possível ver em tempo real.

O participante também consegue visualizar outros usuários que estão na sessão de desenvolvimento colaborativo em tempo real e quais recursos estão compartilhados:

Painel de status da sessão de desenvolvimento em equipe da extensão live share

Administrando uma sessão de desenvolvimento em equipe online

O administrador possui total controle sobre a sessão, podendo inclusive terminar ela quando achar necessário.

Administrar sessão de desenvolvimento colaborativo em tempo real

Dentre outras coisas o administrador pode:

  • Controlar os participantes online, mutar o microfone ou remover;
  • Compartilhar serviços com os membros da sessão a partir da porta. É possível facilmente compartilhar servidor web, banco de dados e qualquer outro que esteja ouvindo em uma porta específica;
  • Compartilhar sessões de terminal com outros participantes.
PHP - Recursos essenciais
Curso de PHP - Recursos essenciais
CONHEÇA O CURSO

Considerações finais sobre a extensão Live Share do Visual Studio

A extensão é uma ótima ferramenta para o desenvolvimento em tempo real para dois ou mais desenvolvedores que precisam programar em conjunto. Pode ser uma ótima escolha para a prática de pair programming da metodologia Extreme Programming XP, orientação do lider técnico da equipe ou daquele pessoal sênior que sabe muito.

Criando repositórios para o NuGet

Existem situações onde o NuGet não pode ser acessado livremente. Mesmo que os desenvolvedores desejem ter acesso irrestrito a este gerenciador de pacotes, políticas de segurança da rede, ou mesmo limitações do ambiente (um local sem internet) podem limitar este acesso.

Felizmente o NuGet indica soluções para essas situações.

C# (C Sharp) Básico
Curso de C# (C Sharp) Básico
CONHEÇA O CURSO

Servidor local

Geralmente quando estamos sem internet, em uma longa viagem, ou em um cliente que não libera o acesso à rede, a instalação dos pacotes NuGet fica comprometida. Não tem como instalar um pacote sem ter acesso ao nuget.org, ou tem?

Ao acessar um pacote no nuget.org, é possível ver que ele pode ser baixado:

Se ele possibilita o download do pacote, então deve ter uma forma de listá-lo offline, certo? Sim, tem, podemos criar uma pasta na rede ou no computador local, com os pacotes mais comuns:

E no Visual Studio, em Tools > NuGet Package Manager > Package Sources, é possível definir a pasta como uma fonte para o NuGet:

Com isso, quando o computador não tiver acesso à internet, ele irá procurar os pacotes no servidor local.

NuGet.Sever

O NuGet.Server é um pacote que pode ser adicionado a uma aplicação ASP.NET, e a transforma em um servidor de pacotes.

A sua configuração é simples, basta criar uma aplicação web do ASP.NET no Visual Studio, e nela adicionar o pacote NuGet.Server:

Ao fazer isso, será criada uma pasta chamada Packages no projeto:

É nesta pasta que deve ser adicionados os pacotes:

Só é importante definir nas propriedades do arquivo que ele sempre deve ser copiado quando a aplicação for executada ou publicada:

E ao executar a aplicação:

Serão mostradas as URLs do servidor NuGet, que você pode utilizar para configurar no Package Sources, ou mesmo para enviar novos pacotes.

C# (C Sharp) Intermediário
Curso de C# (C Sharp) Intermediário
CONHEÇA O CURSO

A apikey que deve ser informada para se enviar novos pacotes, pode ser configurada no arquivo web.config da aplicação, em:

<appSettings>
    <add key="apiKey" value="" />
</appSettings>

Mas você desabilitar esta exigência no atributo requireApiKey:

<appSettings>
    <add key="requireApiKey" value="false" />
</appSettings>

Na página do NuGet, você pode ver mais opções de configuração.

NuGet Gallery

Caso não queria criar um projeto, você pode copiar do GitHub o NuGet Gallery, e publicá-lo em um servidor IIS. As configurações dele serão iguais do NuGet.Server.

Haverá uma pasta Packages onde os pacotes poderão ser adicionados e uma ApiKey deve ser definida na chave apiKey do arquivo web.config.

Serviços de terceiros

Caso não queira utilizar nenhuma das opções acima, você pode utilizar algum serviço de terceiro, como os abaixo:

Eles permitem a criação de um servidor de pacote privado. A vantagem deste método, é que o serviço que se encarregará de manter os pacotes do servidor privado atualizados.

C# (C Sharp) Avançado
Curso de C# (C Sharp) Avançado
CONHEÇA O CURSO

Conclusão

O NuGet possui várias funcionalidades que não são muito conhecidas, mas que podem ser utilizadas quando os desenvolvedores quiserem ter mais controle sobre os pacotes, ou quando houver certos receios quanto ao seu uso irrestrito.

Operações CRUD no ASP.NET MVC 5 com o ADO.NET

Conversando com um amigo ele contou como funciona a estrutura da aplicação ASP.NET MVC da empresa onde ele recentemente começou a trabalhar.

A minha surpresa foi saber que durante a migração da aplicação desktop para ASP.NET MVC eles optaram por continuar utilizando a mesma estrutura de acesso à base de dados com o clássico e bom ADO.NET.

Não pretendo discorrer nesse artigo se essa foi uma boa ou má escolha ou se seria melhor modificar todo o acesso à base de dados durante a migração e optar por outro framework ORM.

O que essa situação me mostrou é que mesmo com
várias opções, ainda há quem prefira utilizar o ADO.NET e não há muitos artigos abordando o uso deste framework com o ASP.NET MVC.

Sendo assim, mostrarei aqui como isso pode ser feito. Então, mãos à massa!

C# (C Sharp) - ASP.NET MVC
Curso de C# (C Sharp) - ASP.NET MVC
CONHEÇA O CURSO

Criando uma aplicação ASP.NET MVC

Para esse artigo estou utilizando o Visual Studio Community 2015. Nele, siga os procedimentos abaixo para criar o projeto.

  1. Com o Visual Studio aberto, em “File”, clique em “New > Project”, selecione o template “ASP.NET Web Application”, por fim, clique em OK.

A tela abaixo será apresentada:

  1. Como mostra a imagem, selecione a opção de template Empty e adicione a referência ao MVC. Depois clique em OK para criar o projeto:

Pronto! O nosso projeto está criado.

Criando classes do domínio

Aqui não vou me ater muito a padrões de projetos, mas para ficar próximo a uma estrutura comum quando se faz uso de um framework ORM, vamos criar no projeto classes de domínio e um repositório.

A classe de domínio será idêntica com uma classe de domínio de um framework ORM:

public class Pessoa
{
    public int Id { get; set; }

    [Required(ErrorMessage = "O campo nome é obrigatório.")]
    public string Nome { get; set; }

    public string Email { get; set; }

    public string Cidade { get; set; }

    public string Endereco { get; set; }
}

A anotação Required definida acima será utilizada para a validação na View.

Como a aplicação está utilizando o ADO.NET ela não poderá fazer uso das migrations do Entity (ou qualquer outro recurso equivalente em outro framework ORM), então, as classes de domínio devem representar exatamente a estrutura das tabelas do banco.

Ou seja, quando se utiliza o ADO.NET, deve ser empregado o princípio Database-First.

Criando o repositório

A criação do repositório é a parte parte mais crítica de uma aplicação que faz uso do ADO.NET, pois é nesta fase que as configurações de acesso são definidas.

Recomenda-se definir uma uma interface, mas neste exemplo, utilizarei uma classe abstrata:

public abstract class AbstractRepository<TEntity, TKey>
    where TEntity : class
{
    protected string StringConnection { get; } = WebConfigurationManager.ConnectionStrings["DatabaseCrud"].ConnectionString;

    public abstract List<TEntity> GetAll();
    public abstract TEntity GetById(TKey id);
    public abstract void Save(TEntity entity);
    public abstract void Update(TEntity entity);
    public abstract void Delete(TEntity entity);
    public abstract void DeleteById(TKey id);
}

Nesta classe, além dos métodos do repositório, é definido um atributo readonly (somente leitura), que obterá do arquivo web.config a string de conexão com o banco.

Nele é necessário definir essa string:

<connectionStrings>
  <add name="DatabaseCrud" connectionString="Data Source=(localdb)MSSQLLocalDB; Initial Catalog=DatabaseCrud-20161026144350; Integrated Security=True; MultipleActiveResultSets=True;"
    providerName="System.Data.SqlClient" />
</connectionStrings>

Agora implementaremos o repositório da nossa entidade:

public class PessoaRepository : AbstractRepository<Pessoa, int>
{
    ///<summary>Exclui uma pessoa pela entidade
    ///<param name="entity">Referência de Pessoa que será excluída.</param>
    ///</summary>
    public override void Delete(Pessoa entity)
    {
        using (var conn = new SqlConnection(StringConnection))
        {
            string sql = "DELETE Pessoa Where Id=@Id";
            SqlCommand cmd = new SqlCommand(sql, conn);
            cmd.Parameters.AddWithValue("@Id", entity.Id);
            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
    }

    ///<summary>Exclui uma pessoa pelo ID
    ///<param name="id">Id do registro que será excluído.</param>
    ///</summary>
    public override void DeleteById(int id)
    {
        using (var conn = new SqlConnection(StringConnection))
        {
            string sql = "DELETE Pessoa Where Id=@Id";
            SqlCommand cmd = new SqlCommand(sql, conn);
            cmd.Parameters.AddWithValue("@Id", id);
            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
    }

    ///<summary>Obtém todas as pessoas
    ///<returns>Retorna as pessoas cadastradas.</returns>
    ///</summary>
    public override List<Pessoa> GetAll()
    {
        string sql = "Select Id, Nome, Email, Cidade, Endereco FROM Pessoa ORDER BY Nome";
        using (var conn = new SqlConnection(StringConnection))
        {
            var cmd = new SqlCommand(sql, conn);
            List<Pessoa> list = new List<Pessoa>();
            Pessoa p = null;
            try
            {
                conn.Open();
                using (var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
                {
                    while (reader.Read())
                    {
                        p = new Pessoa();
                        p.Id = (int)reader["Id"];
                        p.Nome = reader["Nome"].ToString();
                        p.Email = reader["Email"].ToString();
                        p.Cidade = reader["Cidade"].ToString();
                        p.Endereco = reader["Endereco"].ToString();
                        list.Add(p);
                    }
                }
            }
            catch(Exception e)
            {
                throw e;
            }
            return list;
        }
    }

    ///<summary>Obtém uma pessoa pelo ID
    ///<param name="id">Id do registro que obtido.</param>
    ///<returns>Retorna uma referência de Pessoa do registro encontrado ou null se ele não for encontrado.</returns>
    ///</summary>
    public override Pessoa GetById(int id)
    {
        using (var conn = new SqlConnection(StringConnection))
        {
            string sql = "Select Id, Nome, Email, Cidade, Endereco FROM Pessoa WHERE Id=@Id";
            SqlCommand cmd = new SqlCommand(sql, conn);
            cmd.Parameters.AddWithValue("@Id", id);
            Pessoa p = null;
            try
            {
                conn.Open();
                using (var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
                {
                    if (reader.HasRows)
                    {
                        if (reader.Read())
                        {
                            p = new Pessoa();
                            p.Id = (int)reader["Id"];
                            p.Nome = reader["Nome"].ToString();
                            p.Email = reader["Email"].ToString();
                            p.Cidade = reader["Cidade"].ToString();
                            p.Endereco = reader["Endereco"].ToString();
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return p;
        }
    }

    ///<summary>Salva a pessoa no banco
    ///<param name="entity">Referência de Pessoa que será salva.</param>
    ///</summary>
    public override void Save(Pessoa entity)
    {
        using (var conn = new SqlConnection(StringConnection))
        {
            string sql = "INSERT INTO Pessoa (Nome, Email, Cidade, Endereco) VALUES (@Nome, @Email, @Cidade, @Endereco)";
            SqlCommand cmd = new SqlCommand(sql, conn);
            cmd.Parameters.AddWithValue("@Nome", entity.Nome);
            cmd.Parameters.AddWithValue("@Email", entity.Email);
            cmd.Parameters.AddWithValue("@Cidade", entity.Cidade);
            cmd.Parameters.AddWithValue("@Endereco", entity.Endereco);
            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
    }

    ///<summary>Atualiza a pessoa no banco
    ///<param name="entity">Referência de Pessoa que será atualizada.</param>
    ///</summary>
    public override void Update(Pessoa entity)
    {
        using (var conn = new SqlConnection(StringConnection))
        {
            string sql = "UPDATE Pessoa SET Nome=@Nome, Email=@Email, Cidade=@Cidade, Endereco=@Endereco Where Id=@Id";
            SqlCommand cmd = new SqlCommand(sql, conn);
            cmd.Parameters.AddWithValue("@Id", entity.Id);
            cmd.Parameters.AddWithValue("@Nome", entity.Nome);
            cmd.Parameters.AddWithValue("@Email", entity.Email);
            cmd.Parameters.AddWithValue("@Cidade", entity.Cidade);
            cmd.Parameters.AddWithValue("@Endereco", entity.Endereco);
            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
    }
}

Note que em todos os métodos a conexão é aberta manualmente. Ela será fechada graças ao uso do using. E todos os métodos “lançam” as exceções geradas para o respectivo método do repositório que fora invocado.

C# (C Sharp) - ASP.NET MVC
Curso de C# (C Sharp) - ASP.NET MVC
CONHEÇA O CURSO

Criando o Controller

Caso estivéssemos utilizando o Entity, o controller poderia ser criado já com as views, mas no nosso ambiente, teremos que criá-los separadamente. O controller será criado com as actions:

Com o uso do repositório terá o código abaixo:

public class PessoaController : Controller
{
    private PessoaRepository respository = new PessoaRepository();
    // GET: Pessoa
    public ActionResult Index()
    {
        return View(respository.GetAll());
    }

    // GET: Pessoa/Create
    public ActionResult Create()
    {
        return View();
    }

    // POST: Pessoa/Create
    [HttpPost]
    public ActionResult Create(Pessoa pessoa)
    {
        if (ModelState.IsValid)
        {
            respository.Save(pessoa);
            return RedirectToAction("Index");
        }
        else { 
            return View(pessoa);
        }
    }

    // GET: Pessoa/Edit/5
    public ActionResult Edit(int id)
    {
        var pessoa = respository.GetById(id);

        if (pessoa == null)
        {
            return HttpNotFound();
        }

        return View(pessoa);
    }

    // POST: Pessoa/Edit/5
    [HttpPost]
    public ActionResult Edit(Pessoa pessoa)
    {
        if (ModelState.IsValid)
        {
            respository.Update(pessoa);
            return RedirectToAction("Index");
        }
        else
        {
            return View(pessoa);
        }
    }

    // POST: Pessoa/Delete/5
    [HttpPost]
    public ActionResult Delete(int id)
    {
        respository.DeleteById(id);
        return Json(respository.GetAll());      
    }
}

Pronto, agora só é necessário definir as Views.

Criando as views

O código das views é bem simples, pois podemos utilizar o scaffolding do Visual Studio.

No controller clique com o botão direito sobre a
action Index, e selecione Add View. A tela abaixo será apresentada:

Configure os dados conforme a imagem acima. Agora, modifique o código gerado para este:

@model IEnumerable<CRUDUsingMVCwithAdoNet.Models.Pessoa>
@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>

<p>
    @Html.ActionLink("Adicionar Pessoa", "Create")
</p>
<table class="table" id="tblPessoas">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Nome)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Email)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Cidade)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Nome)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Email)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Cidade)
                </td>
                <td>
                    @Html.ActionLink("Editar", "Edit", new { id = item.Id }) |
                    <button type="button" class="btn btn-link" data-item="@item.Id">Deletar</button>
                </td>
            </tr>
        }
    </tbody>
</table>
@section Scripts {
<script type="text/javascript">
        $(document).ready(function () {
            $(".btn-link").click(function () {
                var id = $(this).attr('data-item');
                if (confirm("Você tem certeza que gostaria de excluir este registro?")) {
                    $.ajax({
                        method: "POST",
                        url: "/Pessoa/Delete/" + id,
                        success: function (data) {
                            $("#tblPessoas tbody > tr").remove();
                            $.each(data, function (i, pessoa) {
                                $("#tblPessoas tbody").append(
                                    "<tr>" +
                                    "   <td>" + pessoa.Nome + "</td>" +
                                    "   <td>" + pessoa.Email + "</td>" +
                                    "   <td>" + pessoa.Cidade + "</td>" +
                                    "   <td>" +
                                    "       <a href='/Pessoa/Edit/" + pessoa.Id + "'>Editar</a> |" +
                                    "       <button type="button" class="btn btn-link" data-item="" + pessoa.Id + "">Deletar</button>" +
                                    "   </td>" +
                                    "</tr>"
                                );
                            });
                        },
                        error: function (data) {
                            alert("Houve um erro na pesquisa.");
                        }
                    });
                }
            });
        });
</script>
}

Como mostra o código acima, para não ser necessário criar uma view de exclusão, esta funcionalidade já é definida na listagem.

Repita o mesmo procedimento para termos a view Create:

@model CRUDUsingMVCwithAdoNet.Models.Pessoa
@{
    ViewBag.Title = "Cadastrar";
}

<h2>Cadastrar nova Pessoa</h2>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Pessoa</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Nome, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Nome, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Nome, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Cidade, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Cidade, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Cidade, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Endereco, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Endereco, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Endereco, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Cadastrar" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>
<script src ="~/Scripts/jquery.validate.min.js" />
<script src ="~/Scripts/jquery.validate.unobtrusive.min.js" />

E agora a view Edit:

@model CRUDUsingMVCwithAdoNet.Models.Pessoa
@{
    ViewBag.Title = "Editar";
}

<h2>Editar</h2>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Pessoa</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.Id)

        <div class="form-group">
            @Html.LabelFor(model => model.Nome, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Nome, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Nome, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Cidade, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Cidade, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Cidade, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Endereco, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Endereco, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Endereco, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Salvar" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Voltar a listagem", "Index")
</div>
<script src="~/Scripts/jquery.validate.min.js" />
<script src="~/Scripts/jquery.validate.unobtrusive.min.js" />

Como criamos o projeto a partir de um template vazio, não se esqueça de adicionar os scripts do jQuery Validation (https://jqueryvalidation.org/) e do jQuery Validation Unobtrusive (https://github.com/aspnet/jquery-validation-unobtrusive).

Pronto! A aplicação está pronta. Agora é só testar.

Executando a aplicação

Ao executar a aplicação a tela abaixo será mostrada:

Clique em Adicionar Pessoa para inserir um novo registro.

Se no cadastro nada for informado:

A validação funcionará. Se dados forem informados, o registro será salvo no banco e listado:

Caso clique em Editar, a edição estará funcionando perfeitamente:

E no caso da exclusão é exibida uma caixa de diálogo:

Que ao ser confirmada o registro será excluído:

Conclusão

Os frameworks ORM trazem produtividade para o desenvolvimento, mas o seu uso não pode nos cegar em relação ao legado. Caso seja necessário, é possível fazer uso do ADO.NET no ASP.NET MVC, sem estresse. Esta substituição só será sentida na produtividade devido a não possibilidade de uso de alguns recursos do Visual Studio.

Windows Server 2016 - Internet Information Services
Curso de Windows Server 2016 - Internet Information Services
CONHEÇA O CURSO

© 2004 - 2019 TreinaWeb Tecnologia LTDA - CNPJ: 06.156.637/0001-58 Av. Paulista, 1765, Conj 71 e 72 - Bela Vista - São Paulo - SP - 01311-200