Para mudar a foto da capa de uma fanpage no facebook via api javascript:
(cria um álbum na fanpage da pessoa, e precisa das permissões manage_pages,publish_stream,photo_upload,user_photos)
var fanpageID = "id da minha fanpage";
function acaoDeCapa()
{
$(".meu-link").click(function() {
var tudo = $(this).parent();
var imagem = tudo.find("img").attr("src");
var local = location.protocol + "//" + location.host;
var caminho = local + imagem;
var nomeAlbum = 'Album de Capas';
FB.api('/' + fanpageID + '?fields=access_token', function (response) {
FB.api('/' + fanpageID + '/albums', function(albuns) {
var access_token = response.access_token;
mudarImagem(albuns, nomeAlbum, access_token, caminho);
});
});
});
}
function mudarImagem(albuns, nomeAlbum, access_token, caminho)
{
var albumid = pegarAlbum(albuns, nomeAlbum);
if (albumid != "")
{
subirImagem(access_token, albumid, caminho);
return;
}
var album_params = {
access_token: access_token,
name: nomeAlbum,
message: nomeAlbum
};
FB.api('/' + fanpageID + '/albums', 'post', album_params, function(album) {
subirImagem(access_token, album.id, caminho);
});
}
function pegarAlbum(albuns, nomeAlbum)
{
for(var a in albuns.data)
{
var album = albuns.data[a];
if (album.name == nomeAlbum)
{
return album.id;
}
}
return "";
}
function subirImagem(access_token, album_id, caminho)
{
if (caminho.indexOf("http://localhost") > -1)
caminho = "http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg";
var imagem = { access_token: access_token, url: caminho };
FB.api("/" + album_id + "/photos", "post", imagem, function (imagem_facebook) {
mudarCover(access_token, imagem_facebook.id);
});
}
function mudarCover(access_token, imagem_id)
{
var cover = { access_token: access_token, cover: imagem_id, offset_y: 0 };
FB.api('/' + fanpageID, 'post', cover, function(response_cover) {
console.log(response_cover);
});
}
quinta-feira, 19 de setembro de 2013
quinta-feira, 5 de setembro de 2013
Trófeu Gambiarra MVC
Hoje esbarrei com um problema com rotas no meu adorado MVC.
Se você colocar isso:
context.MapRoute(
"Facebook",
"Facebook/{controller}/{action}/{id}",
new { controller = "Usuario", action = "Inicio", id = UrlParameter.Optional },
new[] { typeof(UsuarioController).Namespace }
);
context.MapRoute(
"Corretores",
"Corretores/{controller}/{action}/{id}",
new { controller = "Usuario", action = "Inicio", id = UrlParameter.Optional },
new[] { typeof(UsuarioController).Namespace }
);
context.MapRoute(
"Facebook",
"Facebook/{controller}/{action}/{id}",
new { controller = "Usuario", action = "Inicio", id = UrlParameter.Optional },
new[] { typeof(UsuarioController).Namespace }
);
context.MapRoute(
"Corretores",
"Corretores/{controller}/{action}/{id}",
new { controller = "Usuario", action = "Inicio", id = UrlParameter.Optional },
new[] { typeof(UsuarioController).Namespace }
);
Quando
você estiver em uma página com a url /Corretores, os links apontarão
para /Facebook. Não só isso, se houver redirecionamento (ex: RedirectToAction, no controller), também irá para /Facebook. Para consertar isso, você pode fazer a coisa horrorosa
abaixo e tudo ficará bem (menos a sua consciência).
context.MapRoute(
"Facebook",
"Face{book}/{controller}/{action}/{id}",
new { controller = "Usuario", action = "Inicio", id = UrlParameter.Optional },
new[] { typeof(UsuarioController).Namespace }
);
context.MapRoute(
"Corretores",
"Corretores/{controller}/{action}/{id}",
new { controller = "Usuario", action = "Inicio", id = UrlParameter.Optional },
new[] { typeof(UsuarioController).Namespace }
);
quinta-feira, 15 de agosto de 2013
Combos que carregam outros combos
Em
um projeto que estou mexendo tem um combo de Estado que recarrega um combo de Cidade.
Para fazer isso, um $.get é feito para uma Action, ela retorna um Json e
esse Json é transformado em HTML no javascript.
Action:
public ActionResult PegarPorEstado(Int32 id)
{
var cidades = cidadeService.PegarCidadePorEstado(id).ToList();
var nomeCidade = new String[cidades.Count];
var idCidade = new Int32[cidades.Count];
var aux = 0;
foreach (var item in cidades)
{
nomeCidade[aux] = item.Nome;
idCidade[aux] = item.ID;
aux = aux + 1;
}
return Json(new { nomeCidade, idCidade }, JsonRequestBehavior.AllowGet);
}
Action:
public ActionResult PegarPorEstado(Int32 id)
{
var cidades = cidadeService.PegarCidadePorEstado(id).ToList();
var nomeCidade = new String[cidades.Count];
var idCidade = new Int32[cidades.Count];
var aux = 0;
foreach (var item in cidades)
{
nomeCidade[aux] = item.Nome;
idCidade[aux] = item.ID;
aux = aux + 1;
}
return Json(new { nomeCidade, idCidade }, JsonRequestBehavior.AllowGet);
}
Javascript:
$.getJSON(urlCidadesPorEstado, { id: uf },
function (data) {
var optionsValues = '';
for (var i = 0; i < data.nomeCidade.length; i++) {
optionsValues += '<option value="' + data.idCidade[i] + '">' + data.nomeCidade[i] + '</option>';
}
$('.select-cidades option:not(:first-child)').remove();
$('.select-cidades option:first-child').after(optionsValues);
}
);
$.getJSON(urlCidadesPorEstado, { id: uf },
function (data) {
var optionsValues = '';
for (var i = 0; i < data.nomeCidade.length; i++) {
optionsValues += '<option value="' + data.idCidade[i] + '">' + data.nomeCidade[i] + '</option>';
}
$('.select-cidades option:not(:first-child)').remove();
$('.select-cidades option:first-child').after(optionsValues);
}
);
O
que eu usei quando precisei fazer isso em outro projeto foi uma
partial. Ela é inserida na View e é o retorno da Action que é
chamada via get. Simplifica o javascript (que não precisa escrever
campos, apenas trocar o HTML de um pedaço da página) e unifica o lugar
onde é criado o combo de Cidades.
Action:
public ActionResult PegarPorEstado(Int32 id)
{
Action:
public ActionResult PegarPorEstado(Int32 id)
{
var model = new MeuModel();
model.Cidades = cidadeService.PegarCidadePorEstado(id).ToList();
return PartialView("MinhaPartial", model);
}
Javascript:
$.getJSON(urlCidadesPorEstado, { id: uf },
function (data) {
$('.select-cidades').parent().html(data);
}
);
$.getJSON(urlCidadesPorEstado, { id: uf },
function (data) {
$('.select-cidades').parent().html(data);
}
);
A
Partial seria o trecho de código onde está o DropDown de cidades, e
herdaria o mesmo Model da View original. Ela teria que ser inserida
sozinha dentro de um elemento na View original, para o novo javascript funcionar sem comer outros códigos.
terça-feira, 13 de agosto de 2013
Entry point not found
Esbarrei neste erro quando tentei usar DropDownListFor em um projeto de MVC4:
"Entry point not found"
Nem vou entrar nos detalhes de stacktrace porque não ajudaram muito.
Depois de muito virar o código, descobri que estava procurando no lugar errado. Removi e inseri diversas vezes a System.Web.Mvc e a System.Web.Webpages do meu projeto MVC, quando deveria ter substituído essas libraries em um projeto do qual ele dependia, uma biblioteca que criei com helpers para MVC.
Nota: não esquecer de verificar não apenas o projeto onde o erro está, como aqueles dos quais ele depende.
"Entry point not found"
Nem vou entrar nos detalhes de stacktrace porque não ajudaram muito.
Depois de muito virar o código, descobri que estava procurando no lugar errado. Removi e inseri diversas vezes a System.Web.Mvc e a System.Web.Webpages do meu projeto MVC, quando deveria ter substituído essas libraries em um projeto do qual ele dependia, uma biblioteca que criei com helpers para MVC.
Nota: não esquecer de verificar não apenas o projeto onde o erro está, como aqueles dos quais ele depende.
segunda-feira, 22 de julho de 2013
Publicando com VS em um servidor novo
Precisei fazer deploy via Visual Studio em um servidor onde antes era usado FTP. Ao tentar fazer o publish, apareceram diversos erros, praticamente uma mensagem da Microsoft "olha, não rola". Encontrei esse tutorial, que pode ser usado por leigos (não entendo muito de configurações em geral).
Como está no tutorial, a lista de erros é mais ou menos esta:
Web deployment task failed.(Could not connect to the destination computer ("[...]").
On the destination computer, make sure that Web Deploy is installed and that the required process
("The Web Management Service") is started.)
This error indicates that you cannot connect to the server. Make sure the service URL is correct,
firewall and network settings on this computer and on the server computer are configured properly,
and the appropriate services have been started on the server.
Unable to connect to the remote server
A connection attempt failed because the connected party did not properly respond after a period
of time, or established connection failed because connected host has failed to respond
O link é este:
http://www.iis.net/learn/publish/troubleshooting-web-deploy/troubleshooting-web-deploy-problems-with-visual-studio
Como está no tutorial, a lista de erros é mais ou menos esta:
Web deployment task failed.(Could not connect to the destination computer ("[...]").
On the destination computer, make sure that Web Deploy is installed and that the required process
("The Web Management Service") is started.)
This error indicates that you cannot connect to the server. Make sure the service URL is correct,
firewall and network settings on this computer and on the server computer are configured properly,
and the appropriate services have been started on the server.
Unable to connect to the remote server
A connection attempt failed because the connected party did not properly respond after a period
of time, or established connection failed because connected host has failed to respond
O link é este:
http://www.iis.net/learn/publish/troubleshooting-web-deploy/troubleshooting-web-deploy-problems-with-visual-studio
quinta-feira, 13 de junho de 2013
Code Generator
Fiz um gerador para ajudar em projetos pequenos. Gera código .NET C#, para MVC4 e tSQL. Pode ser usado para gerar apenas o MVC ou o SQL.
É apenas para projetos simples. Não trata coisas como auto-referência de entidade.
https://bitbucket.org/handhara_akeon/code-generator
É gerado um admin, que possui os CRUDs das entidades, cuja interface é baseada no modelo padrão que vem no MVC. Para configurar o que vai ser gerado, mexa no App Config. Cuidado para não excluir nenhuma chave write_, isso resulta em erro.
Para fazer o front, é possível usar os serviços e copiar Models / Views / Controllers do Admin (tomando o cuidado de tirar o Authorize). Em caso de geração de Views, é necessário colocar no App.Config o nome que será usado para cada entidade / propriedade. Use o modelo que lá existe. Se houver algo que não esteja "traduzido", o programa irá dar erro, avisando onde falta "tradução".
É apenas para projetos simples. Não trata coisas como auto-referência de entidade.
https://bitbucket.org/handhara_akeon/code-generator
- Baixe o código;
- Abra a pasta Renamer;
- Em Renamer.exe.config, coloque o nome do seu projeto na chave NewName
- Use nomes sem caracteres especiais, espaços ou pontos: será o nome do seu projeto no código fonte;
- Execute Renamer.exe;
- Delete as pastas .hg e Renamer e os arquivos .hgignore e .hgtags;
- Abra a solution [seu projeto].Generator
- Crie suas entidades no projeto [seu projeto].Entities (substituindo Father, GrandFather, Pet, Son e Toy, são exemplos e foram usados para testes);
- Execute o projeto;
- Abra a solution com o nome do seu projeto;
- Delete os arquivos referentes a entidades de teste;
- Inclua no projeto os arquivos gerados com base nas suas entidades;
É gerado um admin, que possui os CRUDs das entidades, cuja interface é baseada no modelo padrão que vem no MVC. Para configurar o que vai ser gerado, mexa no App Config. Cuidado para não excluir nenhuma chave write_, isso resulta em erro.
Para fazer o front, é possível usar os serviços e copiar Models / Views / Controllers do Admin (tomando o cuidado de tirar o Authorize). Em caso de geração de Views, é necessário colocar no App.Config o nome que será usado para cada entidade / propriedade. Use o modelo que lá existe. Se houver algo que não esteja "traduzido", o programa irá dar erro, avisando onde falta "tradução".
quinta-feira, 25 de abril de 2013
Web config transforms (Visual Studio)
Às vezes as pessoas adicionam no projeto um arquivo copiado do web.config, só para para homologação / produção. Se você usar o publish do visual studio, isso não é necessário. Você apenas adiciona um arquivo a mais, web.Producao.config por exemplo, que terá apenas o que será alterado no web.config original, e cria o perfil Producao (exemplo) no Visual Studio. Quando for fazer o deploy, você seta aquele perfil, e manda fazer o deploy, que ele irá alterar o que é necessário, e fazer o deploy com o arquivo alterado.
Detalhado:
A diferença das tags é dois atributos a mais, dizendo o que deve ser feito e o critério usado para tanto. Ex:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="connectionString" connectionString="X" xdt:Transform="Replace" xdt:Locator="Match(name)"/>
</connectionStrings>
</configuration>
Assim, se você adicionar coisas novas ao web.config, não terá que ficar fazendo merge, nem terá aquele risco de alguém substituir o web.config sem saber.
Detalhado:
- Ao lado do botão de play, tem um combo escrito Debug (ou Release). Clique na opção Configuration Manager;
- Em Active Solution Configuration, clique em New;
- Dê um nome à sua configuração nova (Producao?) e escolha qual a configuração antiga será copiada;
- Vá no web.config, clique com o botão direito e clique em Add Config Transforms;
- Surgirá, dentro do web.config, um arquivo chamado web.[sua configuração].config. Dentro dele, você pode colocar os atributos que quer mudar ou adicionar.
A diferença das tags é dois atributos a mais, dizendo o que deve ser feito e o critério usado para tanto. Ex:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="connectionString" connectionString="X" xdt:Transform="Replace" xdt:Locator="Match(name)"/>
</connectionStrings>
</configuration>
Assim, se você adicionar coisas novas ao web.config, não terá que ficar fazendo merge, nem terá aquele risco de alguém substituir o web.config sem saber.
terça-feira, 16 de abril de 2013
CSS selectors: nth-child x nth-of-type
Quando descobri o nth-child, adorei. O efeito dele é aplicar um estilo a certos elementos de uma lista e a outros não. Por exemplo, tabelas listradas, que antes calculávamos na programação quais eram as linhas pares e ímpares para aplicar ou não um estilo.
Algumas vezes, me pareceu ter um comportamento estranho. De repente, eu pedia para ele pegar as linhas ímpares e ele pegava as pares. Recentemente descobri que o problema era quando havia um intruso entre os filhos. Por exemplo*:
<style>
ul li:nth-child(2n)
{
background: red;
}
</style>
<ul>
<input type="hidden" />
<li><input /></li>
<li><input /></li>
</ul>
Até esbarrar com a situação e entender, eu achava que este código deveria colorir de vermelho sempre o segundo elemento LI a cada dois. Porém, sendo nth-child, ele considera também o hidden. Sendo assim, o primeiro LI é o segundo elemento desta lista.
Quando você tenta fazer um CSS genérico para o site, com itens gerados automaticamente, isso começa a ser um problema. Me deparei com isso hoje, ao precisar adicionar uma tag script (não podia separar em arquivo js porque inclui código C#).
A solução foi um selector que eu ainda não conhecia: nth-of-type. Este sim pega apenas os LIs.
<style>
ul li:nth-of-type(2n)
{
background: red;
}
</style>
<ul>
<input type="hidden" />
<li><input /></li>
<li><input /></li>
</ul>
Não importa quantos hiddens sejam colocados ali, ele continua pintando de vermelho o segundo elemento de cada dois LI.
* Um UL não deve conter elementos fora LIs. Isto é apenas um exemplo.
Algumas vezes, me pareceu ter um comportamento estranho. De repente, eu pedia para ele pegar as linhas ímpares e ele pegava as pares. Recentemente descobri que o problema era quando havia um intruso entre os filhos. Por exemplo*:
<style>
ul li:nth-child(2n)
{
background: red;
}
</style>
<ul>
<input type="hidden" />
<li><input /></li>
<li><input /></li>
</ul>
Até esbarrar com a situação e entender, eu achava que este código deveria colorir de vermelho sempre o segundo elemento LI a cada dois. Porém, sendo nth-child, ele considera também o hidden. Sendo assim, o primeiro LI é o segundo elemento desta lista.
Quando você tenta fazer um CSS genérico para o site, com itens gerados automaticamente, isso começa a ser um problema. Me deparei com isso hoje, ao precisar adicionar uma tag script (não podia separar em arquivo js porque inclui código C#).
A solução foi um selector que eu ainda não conhecia: nth-of-type. Este sim pega apenas os LIs.
<style>
ul li:nth-of-type(2n)
{
background: red;
}
</style>
<ul>
<input type="hidden" />
<li><input /></li>
<li><input /></li>
</ul>
Não importa quantos hiddens sejam colocados ali, ele continua pintando de vermelho o segundo elemento de cada dois LI.
* Um UL não deve conter elementos fora LIs. Isto é apenas um exemplo.
Herança Múltipla em C#
Alguém já se pegou precisando fazer uma herança múltipla em C#? A própria ideia é bem estranha. Em tese, você herda algo genérico e extende. Porque misturar duas coisas?
Caso apareça essa necessidade, você tenha pensado bem e visto que não tem como, que você não pode transformar suas classes em interfaces, que você vai efetivamente usar os códigos separados que não pode colocar as duas classes como filhas da classe que você queria fazer herdá-las... Um milhão de aspectos a analisar. O bom seria que você pensasse muito antes de fazer.
Estou no terceiro parágrafo. Tem certeza mesmo que é isso que você quer? Ok. Vamos lá.
public class Ornitorrinco : Pato, Castor
{
}
public class Pato
{
public Boolean BicoMexendo { get; set; }
public void MexeBico()
{
BicoMexendo = true;
}
}
public class Castor
{
public Boolean CaldaMexendo { get; set; }
public void MexeCalda()
{
CaldaMexendo = true;
}
}
A essa altura, o Visual Studio me diz que está esperando uma interface. É, não existe Herança Múltipla em C#. Pois é. Que triste, não? Aiai. Ok, ainda posso herdar as propriedades.
public interface ITemBico
{
Boolean BicoMexendo { get; set; }
}
public interface ITemCalda
{
Boolean CaldaMexendo { get; set; }
}
public class Ornitorrinco : ITemBico, ITemCalda
{
public Boolean BicoMexendo { get; set; }
public Boolean CaldaMexendo { get; set; }
}
public class Pato : ITemBico
{
public Boolean BicoMexendo { get; set; }
public void MexeBico()
{
BicoMexendo = true;
}
}
public class Castor : ITemCalda
{
public Boolean CaldaMexendo { get; set; }
public void MexeCalda()
{
CaldaMexendo = true;
}
}
Uma das sugestões que vi na internet é criar um método em Ornitorrinco, inicializar um Pato / Castor dentro, e chamar o método dele. Mas como eu faço com que isso interfira nas MINHAS variáveis? Igualo o valor depois?
A ideia que tive veio de algo que adoro fazer: extender classes. Principalmente com String, ajuda bastante no entendimento do código. A parte que interessa nesse momento é que também é possível extender uma interface. O que me possibilita...
public interface ITemBico
{
Boolean BicoMexendo { get; set; }
}
public static class TemBico
{
public static void MexeBico(this ITemBico temBico)
{
temBico.BicoMexendo = true;
}
}
public interface ITemCalda
{
Boolean CaldaMexendo { get; set; }
}
public static class TemCalda
{
public static void MexeCalda(this ITemCalda temCalda)
{
temCalda.CaldaMexendo = true;
}
}
public class Ornitorrinco : ITemBico, ITemCalda
{
public Boolean BicoMexendo { get; set; }
public Boolean CaldaMexendo { get; set; }
}
public class Pato : ITemBico
{
public Boolean BicoMexendo { get; set; }
}
public class Castor : ITemCalda
{
public Boolean CaldaMexendo { get; set; }
}
Agora eu posso fazer isso...
var meuOrnitorrinco = new Ornitorrinco();
var meuPato = new Pato();
var meuCastor = new Castor();
meuOrnitorrinco.MexeBico();
meuOrnitorrinco.MexeCalda();
meuPato.MexeBico();
meuCastor.MexeCalda();
...sabendo que o código não está repetido e correndo risco de uma correção ou um refactor afetar uma coisa e não outra. É, eu sei, o último código ficou parecendo música da Xuxa.
Sim, é possível. Raramente será a solução correta. As propriedades usadas pelos métodos terão que ficar expostas. Se for fazer, tenha certeza de não usar o mesmo nome de método para duas interfaces que serão herdadas pela mesma classe.
Meu exemplo não é um Ornitorrinco a toa...
Caso apareça essa necessidade, você tenha pensado bem e visto que não tem como, que você não pode transformar suas classes em interfaces, que você vai efetivamente usar os códigos separados que não pode colocar as duas classes como filhas da classe que você queria fazer herdá-las... Um milhão de aspectos a analisar. O bom seria que você pensasse muito antes de fazer.
Estou no terceiro parágrafo. Tem certeza mesmo que é isso que você quer? Ok. Vamos lá.
public class Ornitorrinco : Pato, Castor
{
}
public class Pato
{
public Boolean BicoMexendo { get; set; }
public void MexeBico()
{
BicoMexendo = true;
}
}
public class Castor
{
public Boolean CaldaMexendo { get; set; }
public void MexeCalda()
{
CaldaMexendo = true;
}
}
A essa altura, o Visual Studio me diz que está esperando uma interface. É, não existe Herança Múltipla em C#. Pois é. Que triste, não? Aiai. Ok, ainda posso herdar as propriedades.
public interface ITemBico
{
Boolean BicoMexendo { get; set; }
}
public interface ITemCalda
{
Boolean CaldaMexendo { get; set; }
}
public class Ornitorrinco : ITemBico, ITemCalda
{
public Boolean BicoMexendo { get; set; }
public Boolean CaldaMexendo { get; set; }
}
public class Pato : ITemBico
{
public Boolean BicoMexendo { get; set; }
public void MexeBico()
{
BicoMexendo = true;
}
}
public class Castor : ITemCalda
{
public Boolean CaldaMexendo { get; set; }
public void MexeCalda()
{
CaldaMexendo = true;
}
}
Uma das sugestões que vi na internet é criar um método em Ornitorrinco, inicializar um Pato / Castor dentro, e chamar o método dele. Mas como eu faço com que isso interfira nas MINHAS variáveis? Igualo o valor depois?
A ideia que tive veio de algo que adoro fazer: extender classes. Principalmente com String, ajuda bastante no entendimento do código. A parte que interessa nesse momento é que também é possível extender uma interface. O que me possibilita...
public interface ITemBico
{
Boolean BicoMexendo { get; set; }
}
public static class TemBico
{
public static void MexeBico(this ITemBico temBico)
{
temBico.BicoMexendo = true;
}
}
public interface ITemCalda
{
Boolean CaldaMexendo { get; set; }
}
public static class TemCalda
{
public static void MexeCalda(this ITemCalda temCalda)
{
temCalda.CaldaMexendo = true;
}
}
public class Ornitorrinco : ITemBico, ITemCalda
{
public Boolean BicoMexendo { get; set; }
public Boolean CaldaMexendo { get; set; }
}
public class Pato : ITemBico
{
public Boolean BicoMexendo { get; set; }
}
public class Castor : ITemCalda
{
public Boolean CaldaMexendo { get; set; }
}
Agora eu posso fazer isso...
var meuOrnitorrinco = new Ornitorrinco();
var meuPato = new Pato();
var meuCastor = new Castor();
meuOrnitorrinco.MexeBico();
meuOrnitorrinco.MexeCalda();
meuPato.MexeBico();
meuCastor.MexeCalda();
...sabendo que o código não está repetido e correndo risco de uma correção ou um refactor afetar uma coisa e não outra. É, eu sei, o último código ficou parecendo música da Xuxa.
Sim, é possível. Raramente será a solução correta. As propriedades usadas pelos métodos terão que ficar expostas. Se for fazer, tenha certeza de não usar o mesmo nome de método para duas interfaces que serão herdadas pela mesma classe.
Meu exemplo não é um Ornitorrinco a toa...
sábado, 13 de abril de 2013
MVC4 Partials
Hoje eu estava alterando uma View, para colocar uma Partial dentro dela.
Me deparei com um problema quando tentei renderizar a Partial. Apesar de eu estar passando uma propriedade model esperado como model para a função Partial (Html.Partial), ele continuava dizendo que eu tentava passar o model principal. E dava o erro:
The model item passed into the dictionary is of type '[model principal]', but this dictionary requires a model item of type '[model esperado]'.
O problema é que a propriedade era nula. Então o método Html.Partial estava pegando o pai da propriedade, que realmente era meu model principal. Por isso o erro. Resolvi isso colocando no construtor do model principal uma inicialização para a propriedade do model esperado.
Me deparei com um problema quando tentei renderizar a Partial. Apesar de eu estar passando uma propriedade model esperado como model para a função Partial (Html.Partial), ele continuava dizendo que eu tentava passar o model principal. E dava o erro:
The model item passed into the dictionary is of type '[model principal]', but this dictionary requires a model item of type '[model esperado]'.
O problema é que a propriedade era nula. Então o método Html.Partial estava pegando o pai da propriedade, que realmente era meu model principal. Por isso o erro. Resolvi isso colocando no construtor do model principal uma inicialização para a propriedade do model esperado.
quarta-feira, 20 de março de 2013
Biblioteca
Publiquei no bitbucket o código da biblioteca que crie para o DFM e para o Stories, a Ak.
Está em constante revisão. Usem o que quiserem.
quinta-feira, 14 de março de 2013
Query com Reflection
Hoje tive que criar queries na mão, pois preciso fazer uma importação e o NHibernate demoraria muito para salvar os objetos.
Estava com preguiça de criar as queries uma a uma, olhando as propriedades do objeto. Então lembrei de reflection. Por que não? Afinal de contas, virei programadora porque detesto trabalho repetitivo...
Fiz uma iteração pelos tipos que queria e gravei de um arquivo.
using System;
using System.Collections.Generic;
using System.IO;
var tipos = new[]
{
typeof ([tipo 1]),
typeof ([tipo 2]),
};
var query = new List<String>();
foreach (var tipo in tipos)
{
var colunas = new List<String>();
var valores = new List<String>();
var nomeTipo = tipo.Name.ToLower();
foreach (var propertyInfo in tipo.GetProperties())
{
if (propertyInfo.Name == "ID")
continue;
colunas.Add(propertyInfo.Name);
valores.Add("\" + " + nomeTipo + "." + propertyInfo.Name + ".ToSql() + \"");
}
query.Add("@\"Insert into " + nomeTipo + " (" + String.Join(", ", colunas) + ")");
query.Add(" Values (" + String.Join(", ", valores) + ")\";");
var atribuicao = new List<String>();
query.Add("@\"Update " + nomeTipo + " set ");
foreach (var propertyInfo in tipo.GetProperties())
{
if (propertyInfo.Name == "ID")
continue;
atribuicao.Add(propertyInfo.Name + " = \" + " + nomeTipo + "."
+ propertyInfo.Name + ".ToSql() + \"");
}
query.Add(String.Join(", ", atribuicao) + " where ID = \" + "
+ nomeTipo + ".ID + \"\";");
}
File.WriteAllLines([caminho do arquivo], query);
Então você pega o resultado do arquivo e cola no seu código. Melhor que ficar copiando as propriedades uma por uma.
Estava com preguiça de criar as queries uma a uma, olhando as propriedades do objeto. Então lembrei de reflection. Por que não? Afinal de contas, virei programadora porque detesto trabalho repetitivo...
Fiz uma iteração pelos tipos que queria e gravei de um arquivo.
using System;
using System.Collections.Generic;
using System.IO;
var tipos = new[]
{
typeof ([tipo 1]),
typeof ([tipo 2]),
};
var query = new List<String>();
foreach (var tipo in tipos)
{
var colunas = new List<String>();
var valores = new List<String>();
var nomeTipo = tipo.Name.ToLower();
foreach (var propertyInfo in tipo.GetProperties())
{
if (propertyInfo.Name == "ID")
continue;
colunas.Add(propertyInfo.Name);
valores.Add("\" + " + nomeTipo + "." + propertyInfo.Name + ".ToSql() + \"");
}
query.Add("@\"Insert into " + nomeTipo + " (" + String.Join(", ", colunas) + ")");
query.Add(" Values (" + String.Join(", ", valores) + ")\";");
var atribuicao = new List<String>();
query.Add("@\"Update " + nomeTipo + " set ");
foreach (var propertyInfo in tipo.GetProperties())
{
if (propertyInfo.Name == "ID")
continue;
atribuicao.Add(propertyInfo.Name + " = \" + " + nomeTipo + "."
+ propertyInfo.Name + ".ToSql() + \"");
}
query.Add(String.Join(", ", atribuicao) + " where ID = \" + "
+ nomeTipo + ".ID + \"\";");
}
File.WriteAllLines([caminho do arquivo], query);
Então você pega o resultado do arquivo e cola no seu código. Melhor que ficar copiando as propriedades uma por uma.
sexta-feira, 1 de março de 2013
Formatação de números e datas (.NET)
Dessa vez o post é bem simples.
Volta e meia esbarro códigos grandes para formatar a exibição de números e datas. Por exemplo, quando o programador precisa exibir o número com zeros à direita ou quer formatar a data e usa as propriedades dela, transformando em string e concatenando.
Exemplo de número:
var tamanhoDesejado = 10;
var totalStr = total.ToString();
var tamanhoAtual = totalStr.Length;
var totalStr = "";
var i = 0;
while (i < (tamanhoDesejado - tamanhoAtual))
{
totalStr += "0";
i++;
}
totalStr += totalStr;
Exemplo de data:
var dataStr = data.Year.ToString()
+ "-" + data.Month.ToString()
+ "-" + data.Day.ToString();
Existe um jeito mais simples de fazer isso, um jeito nativo.
var totalStr = total.ToString("0000000000"); //10 zeros para 10 dígitos
var dataStr = data.ToString("yyyy-MM-dd"); //
Existem caracteres especiais para os dois casos de formatação. Por exemplo, com números, "." (ponto) significa o separador de decimal (em qualquer língua). No caso de data, as letras representam se vai ser usado ano, mês, dia, etc, sendo que é possível dizer o formato (ex: mês com número ou extenso, dia com um ou dois dígitos).
Volta e meia esbarro códigos grandes para formatar a exibição de números e datas. Por exemplo, quando o programador precisa exibir o número com zeros à direita ou quer formatar a data e usa as propriedades dela, transformando em string e concatenando.
Exemplo de número:
var tamanhoDesejado = 10;
var totalStr = total.ToString();
var tamanhoAtual = totalStr.Length;
var totalStr = "";
var i = 0;
while (i < (tamanhoDesejado - tamanhoAtual))
{
totalStr += "0";
i++;
}
totalStr += totalStr;
Exemplo de data:
var dataStr = data.Year.ToString()
+ "-" + data.Month.ToString()
+ "-" + data.Day.ToString();
Existe um jeito mais simples de fazer isso, um jeito nativo.
var totalStr = total.ToString("0000000000"); //10 zeros para 10 dígitos
var dataStr = data.ToString("yyyy-MM-dd"); //
Existem caracteres especiais para os dois casos de formatação. Por exemplo, com números, "." (ponto) significa o separador de decimal (em qualquer língua). No caso de data, as letras representam se vai ser usado ano, mês, dia, etc, sendo que é possível dizer o formato (ex: mês com número ou extenso, dia com um ou dois dígitos).
Assinar:
Postagens (Atom)