Como tratar exceptions

Há duas maneiras de tratar uma exception e dar um re-throw na mesma ,abaixo seguem dois trechos de código:

Código 1:

1: try
2: {
3:
4: }
5: catch(Exception ex)
6: {
7:         throw ex;
8: }

Código 2:

1: try
2: {
3:
4: }
5: catch(Exception ex)
6: {
7:           throw;
8: }

Quando você usa o código 1,você vair dar um Throw no mesmo objeto Exception e como resultado o stack trace original será perdido.O código 2,mantém o stack trace original e isso é muito útil para debugar.

Um dos guias sobre tratamentos de exceptions diz:


Não de um re-throw jogando o mesmo objeto de exception.Isso faz com que o stack trace original da exception seja perdido;use somente “throw”,para dar um re-throw na exception.

A melhor maneira de ver a diferença,é nesse código de exemplo:

1: class Program
2: {
3: static void Main(string[] args)
4: {
5: try
6: {
7:            Method1();
8: }
9: catch (Exception ex)
10: {
11:           throw;
12: }
13: }
14:
15: public static void Method1()
16: {
17:            Method2();
18: }
19:
20: public static void Method2()
21: {
22:            throw new Exception();
23: }
24: }

O seguintestack trace será gerado com o exemplo acima:

at ConsoleApplication2.Program.Method2()
at ConsoleApplication2.Program.Method1()
at ConsoleApplication2.Program.Main(String[] args)
at System.AppDomain.ExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

Quando você dá um throw em ex;ao invés de throw você recebe:

at ConsoleApplication2.Program.Main(String[] args)
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

Como você pode ver o stack trace não possui a chamada dos métodos 1 e 2,então quando você usa throw ex,você pede informações essenciais do debug.

ASP.NET Custom Server control Youtube player

Recentemente em um de meus projetos eu precisei,mostrar vídeos do youtube em várias páginas da minha aplicação.

Então eu decidi criar um custom server control para isso.É bem simples de fazer e pode ser bem útil quando você precisar mostrar vídeos em vários lugares ou precisar mudar a URL do vídeo dinamicamente.

Crie uma nova Class Library com o nome YouTubeControl ou outro qualquer.Crie uma classe Youtube.cs,que herde de
System.Web.UI.Control:


Próximo passo é adicionar as propriedades da classe (Propriedades do player):

  • URL (seta a URL do vídeo)
  • Height (seta a altura do player)
  • Width (seta a largura do player)
  • AllowFullScreen (opção de tela cheia)

O próximo passo é criar o código “embed” do youtube no método RenderControl:

O método RenderControl irá enviar o stream de saída HTML para o browser.Pra fazer isso vamos criar uma instância da classe HtmlGenericControl,pra armazenar o código embed do youtube e setar todas as propriedades do player:

Nosso controle está pronto,após dar um “build” no projeto,basta adicionar a .dll ao seu projeto agora:

Como usar o controle na sua página:

Clique com o botão direito na ToolBox > Escolha “Add Tab” > De o nome de “Custom Controls” para essa tab > Clique com o direito dentro desta tab > Escolha “Choose Items…” >> No Pop-up que abrir,clique na aba .NET Components >> Clique no botão “Browser…” e busque a pasta do projeto que criamos e encontre sua DLL e clique em OK

Pronto agora basta arrastar o controle para sua página e setar as seguintes configurações para teste:

Você pode inclusive setar as configurações do player via código.

Valeu pessoal até a próxima.

Utilizando o controle TreeView com SiteMap com Asp.Net

Neste artigo nós veremos 5 dicas,pra utilizar o controle TreeView do ASP.NET com um “bound” de um sitemap.É bem comum se utilizar do treeView para mostrar o sitemap.

Esse artigo mostra alguns desafios freqüentes que nós encontramos quando utilizamos estes controles.Eu parto do pressuposto de que você sabe o que é o sitemap,e já utilizou o controle TreeView alguma vez.

1. Como dar um bind de um sitemap ao Treeview

Um sitemap é geralmente mostrado na UI usando um controle TreeView.Segue um exemplo de sitemap abaixo:

<?xml version=”1.0″ encoding=”utf-8″ ?>

<siteMap xmlns=”http://schemas.microsoft.com/AspNet/SiteMap-File-1.0&#8243; >

<siteMapNode title=”My Favorites”>

<siteMapNode title=”Favorite Sites”>

<siteMapNode title=”ASP.NET Home” url=”http://www.asp.net&#8221; />

<siteMapNode title=”ASP.NET Articles” url=”http://www.dotnetcurry.com&#8221; />

<siteMapNode title=”Windows Client” url=”http://www.windowsclient.net&#8221; />

<siteMapNode title=”Silverlight” url=”http://silverlight.net&#8221; />

</siteMapNode>

<siteMapNode title=”Favorite Blogs”>

<siteMapNode title=”ScottGu Blog”url=”http://weblogs.asp.net/scottgu&#8221; />

<siteMapNode title=”Technology Blog” url=”http://www.devcurry.com&#8221; />

<siteMapNode title=”SQL Blog” url=”http://www.sqlservercurry.com&#8221; />

<siteMapNode title=”Food Lovers” url=”http://foodatarian.com&#8221; />

</siteMapNode>

</siteMapNode>

</siteMap>

Agora adicione um controle SiteMapDataSource da toolbox (aba data) para sua página e mude a propriedade DataSource do treeView para esse sitemapdatasource como mostrado abaixo:

<div>

<asp:TreeView ID=”TreeView1″ runat=”server” DataSourceID=”SiteMapDataSource1″>

</asp:TreeView>

<asp:SiteMapDataSource ID=”SiteMapDataSource1″ runat=”server” />

</div>

É isso.

2. Remover um nó de um treeview dinamicamente

Pra remover um nó dinamicamente do treeView,use o evento ontreenodedatabound como mostrado abaixo.Nesse exemplo, eu estou removendo o nó “Food Lovers”:

<asp:TreeView ID=”TreeView1″ runat=”server” DataSourceID=”SiteMapDataSource1″

ontreenodedatabound=”TreeView1_TreeNodeDataBound”>

</asp:TreeView>

C#

protected void TreeView1_TreeNodeDataBound(object sender, TreeNodeEventArgs e)

{

if (e.Node.Text == “Food Lovers”)

{

e.Node.Parent.ChildNodes.Remove(e.Node);

}

}

Como você pode ver abaixo o nó “Food Lovers” não é mostrado:

view1

3.Como expandir somente um nó no TreeView

Você já se deparou com a necessidade de só um único nó principal ser expandido em algum momento?Por exemplo,se o nó ’Favorite blogs’ está expandido e o usuário clica no nó ‘Favorite Sites’’ pra expandi-lo,o nó ‘Favorite Blogs’ deve se retrair.Use o seguinte código no evento TreeNodeExpanded:

protected void TreeView1_TreeNodeExpanded(object sender,

TreeNodeEventArgs e)

{

string currValue = e.Node.Value.Trim();

if (e.Node.Parent == null)

{

foreach (TreeNode node in TreeView1.Nodes)

{

if (node.Value != currValue)

{

node.Collapse();

}

}

return;

}

else

{

TreeNode tnode = e.Node.Parent;

foreach (TreeNode node in tnode.ChildNodes)

{

if (node.Value != e.Node.Value)

{

node.Collapse();

}

}

}

}

O resultado é mostrado abaixo:

view2

Como você pode ver ,o nó ‘Favorite Blogs’ retraiu-se quando o usuário clicou no nó ‘Favorite Sites’.

4. Múltiplos sitemaps para múltiplos treeViews

Por padrão,quando você adiciona um novo sitemap ao seu projeto,o arquivo default criado é Web.SiteMap.O SiteMapDatasource por padrão faz referencia a este arquivo.Entretanto,se você quiser criar múltiplo sitemaps, e dar um “bind” neles em diferentes treeViews no seu projeto,aqui você aprenderá como fazer:

Adiciona um conjunto de providers no arquivo web.config como mostrado abaixo:

<system.web>

<siteMap defaultProvider=”SiteMap1″ enabled=”true”>

<providers>

<add siteMapFile=”Web.sitemap” name=”SiteMap1″ type=”System.Web.XmlSiteMapProvider”/>

<add siteMapFile=”web2.sitemap” name=”SiteMap2″ type=”System.Web.XmlSiteMapProvider”/>

</providers>

</siteMap>

Nota:O DefaultProvider é o nome do provider,no nosso caso SiteMap1.

Agora no SiteMapDataSource, especifique o provedor que você quer utilizar.Observe  o atributo ‘SiteMapProvider’.

<asp:SiteMapDataSource ID=”SiteMapDataSource1″ runat=”server”

SiteMapProvider=”SiteMap1″ />

<asp:SiteMapDataSource ID=”SiteMapDataSource2″ runat=”server”

SiteMapProvider=”SiteMap2″ />

Finalmente de um “bind” no dataSource do TreeView para o sitemapDatasource desejado:

<asp:TreeView ID=”TreeView1″ runat=”server”

DataSourceID=”SiteMapDataSource1″>

<asp:TreeView ID=”TreeView2″ runat=”server”

DataSourceID=”SiteMapDataSource2″>

Essa é a maneira de fazer quando você tiver diversos sitemaps no seu projeto.

5. Adicionando URLs alternativas no SiteMapNode

Vamos dizer que você queira especificar uma URL diferente no sitemap e queira dar um “bind” no treeView para essa URL diferenciada em tempo de execução,veja como declarar um atributo personalizado chamado ‘secondUrl’ (ou qualquer outro nome que você deseje) no SiteMapNode no arquivo SiteMap como mostrado abaixo:

<siteMapNode title=”ASP.NET Home” url=”http://www.asp.net&#8221; secondUrl=”http://www.asp.net/ajax&#8221; />

Agora no evento TreeNodeDataBound, recupere o SiteMapNode e pra aqueles nós que contenham esse atributo personalizado.Uma vez que você tenha recuperado o SiteMapNode extraia esse atributo personalizado e mude sua propriedade NavigateUrl como mostrado abaixo:

<asp:TreeView ID=”TreeView1″ runat=”server”

DataSourceID=”SiteMapDataSource1″

OnTreeNodeDataBound=”TreeView1_TreeNodeDataBound”>

</asp:TreeView>

C#

protected void TreeView1_TreeNodeDataBound(object sender, TreeNodeEventArgs e)

{

SiteMapNode node = e.Node.DataItem as SiteMapNode;

if(!string.IsNullOrEmpty(node[“secondUrl”]))

e.Node.NavigateUrl = node[“secondUrl”];

}

Essas foram algumas dicas sobre o treeview e o arquivo sitemap.

Espero que tenha sido útil e até a próxima.

Acessando colunas invisíveis no GridView

Introdução

Quando você mostra dados no GridView você deve sempre tomar cuidado para que a primary key da tabela não seja mostrada.Neste artigo veremos como nós podemos acessar colunas invisíveis do GridView.

Acessando colunas invisíveis:

A primeira coisa que você precisa setar é a propriedade DataKeyNames para a chave primaria de sua tabela,nesse caso”PersonID”.

Código HTML

<asp:GridView runat=”server” AutoGenerateColumns=”False” CellPadding=”4″
DataKeyNames=”PersonID” DataSourceID=”mySource” ForeColor=”#333333″ GridLines=”None”
Width=”266px” OnSelectedIndexChanged=”gvMaster_SelectedIndexChanged”>
<FooterStyle BackColor=”#507CD1″ Font-Bold=”True” ForeColor=”White” />
<RowStyle BackColor=”#EFF3FB” />
<Columns>
<asp:CommandField ShowSelectButton=”True” />
<asp:BoundField DataField=”PersonID” HeaderText=”PersonID” InsertVisible=”False”
ReadOnly=”True” SortExpression=”PersonID” Visible=”False” />
<asp:BoundField DataField=”Name” HeaderText=”Name” SortExpression=”Name” />
<asp:TemplateField HeaderText=”Select”>
<ItemTemplate>
<asp:CheckBox runat=”server” />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<PagerStyle BackColor=”#2461BF” ForeColor=”White” HorizontalAlign=”Center” />
<SelectedRowStyle BackColor=”#D1DDF1″ Font-Bold=”True” ForeColor=”#333333″ />
<HeaderStyle BackColor=”#507CD1″ Font-Bold=”True” ForeColor=”White” />
<EditRowStyle BackColor=”#2461BF” />
<AlternatingRowStyle BackColor=”White” />
</asp:GridView>

Meu gridView possui 3 colunas (esquecendo a coluna do select) chamadas PersonID,Name e uma coluna de checkBox.A coluna PersonID é a chave-primária,e foi marcada como coluna invisível.Nós também temos um botão na página que quando clicado, faz um loop pelos controles do gridView, e mostra as primary keys ,das colunas que tem seu checkbox checado.

Vamos ver o evento do clique do botão:

protected void Button1_Click(object sender, EventArgs e){

string str = String.Empty;

int rowNo = 0;

foreach (GridViewRow row in gvMaster.Rows)

{

bool isChecked = ((CheckBox)row.FindControl(“CheckBox1”)).Checked;

if (isChecked)

{

// Gets the name of the primary key column our primary key is the PersonID

string primaryKey = gvMaster.DataKeyNames[0];

int personID = (int) gvMaster.DataKeys[rowNo].Value;

Response.Write(personID);

}

// increment the row count

rowNo++;

}

Response.Write(str);

}

Até a próxima!

C# 3.0 lambda expressions

A melhor maneira que eu tenho pra descrever lambda expressions é – C# Anonymous Methods mais facilitado.

Mas o que é anonymous method no c# 2.0?

Como você deve saber no c#1.x/2.x era possível escrever códigos da seguinte forma:

class AlgumaClasse

{

delegate void AlgumDelegate();

public void InvokeMethod()

{

AlgumDelegate del = new AlgumDelegate(AlgumMetodo);

del();

}

void AlgumMetodo()

{

Console.WriteLine(“Olá mundo”);

}

}

Depois veio anonymous methods que permitem a você escrever o código acima de uma maneira mais simplificada:

class AlgumaClasse

{

delegate void AlgumDelegate();

public void InvokeMethod()

{

AlgumDelegate del = delegate()

{

Console.WriteLine(“Hello”);

};

del();

}

}

O que você vê depois do “Delegate()”, é um método anônimo.Mesmo sendo melhor que a versão do c#1x. ainda assim requer algum código:

Lambda expressions dão a você uma sintaxe mais concisa e funcional,usando a sintaxe “=>”.

O código acima usando lambda expresssions poderia ser escrito da seguinte forma:

class AlgumaClasse

{

delegate void AlgumDelegate();

public void InvokeMethod()

{

AlgumDelegate del = () => Console.WriteLine(“Hello”) ;

del();

}

}

Geralmente a sintaxe é:

Parâmetros => expressão

Agora óbvio,lambda expressions não são apenas uma maneira mais simples de se escrever métodos anônimos.Eles realmente superam em funcionalidade os métodos anônimos.Porque?:

  • Lambda expressions entendem o tipo de parâmetro que você quer passar mesmo que você os omita.Anonymous methods não permitem.
  • Lambda Expressions podem usar bloco de comandos e expressões.Anonymous methods só aceitam blocos de comandos.
  • Lambda Expressions podem ser passadas como argumentos.

Vamos falar de cada um deles:

Lambda expressions entendem o tipo de parâmetro que você quer passar mesmo que você os omita.Anonymous methods não permitem.

Palavras difíceis para algo simples:

(int x) => x + 1 ; // é o mesmo que
x => x + 1 ;

Na segunda linha o tipo está sendo omitido.

Lambda Expressions podem usar bloco de comandos e expressões.Anonymous methods só aceitam blocos de comandos.

Outra vez palavras difíceis para algo simples:

(int x) => x + 1 ; // é o mesmo que
(int x) => { return x + 1; }

Na segunda linha nós temos um bloco de comando,e na primeira nós temos uma expressão.Então a primeira é igual a segunda mas é mais fácil de entender e escrever.

Lambda Expressions podem ser passadas como argumentos.

Você pode passar lambdas expressions como argumentos para métodos genéricos.Vamos considerar o seguinte exemplo.Vamos dizer que você tivesse,um extension method,como mostrado a seguir:

public static class myExtensions
{
public static void SpankIt<T,U>(
this IEnumerable<T> source,
Func<T, U> someParameter)
{
foreach (T element in source)
Console.WriteLine(“SPANK ” + someParameter(element) + “!!”);
}
}

Você poderia usar o extension method acima,assim:

static void Main(string[] args)
{
List<String> whoToSpank = new List<String>() ;
whoToSpank.Add(“Monkey”) ;
whoToSpank.Add(“Bannana”) ;

whoToSpank.SpankIt(c => “Monkey”) ;
}

E “SPANK MONKEY !!” seria escrito duas vezes.

Mas espere um pouco.O significa o “U” no extension method?Se você colocar um breakpoint no seu extension method você vai perceber que o c# 3.0 é esperto o bastante pra saber que “U” é uma string.Você nunca citou que “U” seria uma string,ele se baseia na lambda expression que você passou.

Você não pode fazer isso com métodos anônimos.

É isso!Abraço.

C# Anonymous types (tipos anônimos)

No meu último post,eu falei sobre a palavra–chave var,se você ainda não o leu,recomendo que o faça agora.

Assumindo que você tenha entendido o que é “var” – vamos em frente!

No c# 2.0,vamos dizer que você quisesse representar uma pessoa,você provavelmente criaria uma classe como esta:

public class Person
{
string hairColor ;
string skinColor ;
int teethCount ;
} ….

Aí entra os tipos anônimos.Agora você pode representar esta mesma classe,sem ter que criar sua estrutura primeiro.Assim:

var monster = new {cabelo=”black”, pele=”green”,dentes=64} ;

A linha de código acima irá funcionar mesmo se você não declarar a classe chamada Person.Isso permite você criar estruturas de dados sem ter que declara-las previamente.

O código acima gera uma classe por trás das cenas que você não vê,assim:

class __Anonymous1
{
private string _cabelo = “black”;
private string _pele = “green”;
private int _dentes   = 64;

public string cabelo {get { return _cabelo; } set { _cabelo = value; }}
public string pele {get { return _pele; } set { _pele = value; }}
public int dentes {get { return _dentes; } set { _dentes = value; }}
}

Por essa classe ser um tipo anonimo ela não possui nome quando é gerada pelo compilador c#,é um “System.Type”.

É isso, até a próxima.

C# 3.0 variáveis tipo var

Desmitificando o c# 3.0 keyword var

No c# 2.0 você podia declarar um integer (ou qualquer outro tipo conhecido)como

int i;

Você também podia escrever algo assim:

int i  = 1;

Ou seja:

<tipo><nomevariavel> = <inicializador>;

Ok,bom.A coisa importante pra se notar é que “i” é um inteiro.Em c# 3.0 o código abaixo é válido:

var i = 1;

Mas o que é “var”?”var” é…hum…uma palavra chave,que resulta em “i” sendo do mesmo tipo do inicializador,nesse caso um inteiro.Então var i = 1;irá resultar em uma variável chamada “i” cujo tipo é integer.

Mas qual a diferença entre “var”,object, e variant(VB6)?

Variants eram tranqueiras,que aceitavam praticamente tudo,ocupando bastante espaço na memória.Objects tem problemas de box e unboxing.E variants e objects ambos não são fortemente tipados.

Note que “i”,é um tipo fortemente tipado para integer – não é nem um objeto nem uma variant,nem carrega os problemas de nenhuma das duas.Para garantir a natureza fortemente tipada que é declarada na palavra chave var, c# 3.0 requer que você ponha no inicializador,na mesma linha da declaração.Também,o inicializador deve ser uma expressão,não um objeto ou coleção,e também não pode ser null.

Você também pode criar arrays de var:

var intArr = new[] {3,1,4,1,5} ;

Espero que tenham entendido,até a próxima!