Aug 17, 2012

Modificar Programaticamente Propriedade ReaderQuotas de um Endpoint - WCF


Estava com um problema no seguinte cenário:

Tenho um WCF, onde faço o "SelfHosting" por um Windows Service. Os dados doendereço eu coloco dinamicamente.

Os arquivos que eu iria enviar para o WCF passavam facilmente os 16Kb padrões da configuração.

Para isso utilizei o seguinte código para adicionar no endpoint que adicionei programaticamente (pelo código compilado, não pelo app.config)







                var endpoint = serviceHostImport.AddServiceEndpoint(typeof(IImportFileService), 
                                        MetadataExchangeBindings.CreateMexHttpBinding(), "mex");

                Binding binding = endpoint.Binding;

                XmlDictionaryReaderQuotas quotas = new XmlDictionaryReaderQuotas();
                quotas.MaxStringContentLength = int.MaxValue;
                quotas.MaxArrayLength = int.MaxValue;
                quotas.MaxBytesPerRead = int.MaxValue;
                quotas.MaxDepth = 64;
                quotas.MaxNameTableCharCount = int.MaxValue;

                binding.GetType().GetProperty("ReaderQuotas").SetValue(binding, quotas, null);

                serviceHostImport.Open();







Repare que a propriedade é adicionada via Reflection.


com isso é possível modificar programaticamente a propriedade ReaderQuotas  do binding de um endpoint WCF para o máximo possível.

Abraços
Rafael

Jul 1, 2012

Como gerar xml à partir de uma classe com atributos customizados





Bom, esses dias precisei criar um XML a partir de uma classe, com os valores das propriedades do objeto.


Realmente existem diversos meios de se fazer isso facilmente, como serialização, entre outros.O problema era que apenas alguns atributos seriam adicionados, não a classe inteira e ainda por cima com nomes diferentes. Por exemplo:

Nome da propriedade "Nome" e nome do atributo xml era "nome_usuario".

Para isso criei um atributo customizado:





  [AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
    public class AtributoXml: Attribute
    {
        private string _nomeXml;
        public string NomeXml
        {
            get { return _nomeXml; }
            set { _nomeXml = value; }
        }
    }





Não esquecer de colocar o "AttributeTargets.Property" , já que assim é possível colocar nas propriedades e não apenas na classe.




No passo seguinte usaremos reflection para acessar dados do atributo e da classe, por isso não esqueça de referência  à "System.Reflection;"

Para conseguir pegar o valor do atributo ,utiliza-se o seguinte códig


var campos = tipo.GetProperties(BindingFlags.Public | BindingFlags.Instance);//Obtém propriedades
foreach (var c in campos)//percorre todos os campos
            {
                  var keys = c.GetCustomAttributes(typeof(AtributoXml), true); //Obtém atributo 
                  nomeCampo = ((AtributoXmlBaseMwl)(keys[0])).NomeXml;

            }


Aplicação real:


public virtual string CriarXml()
        {
            string xmlValue = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>
            <config xmlns=\"http://www.w3schools.com\" 
            xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 
            xsi:schemaLocation=\"http://www.w3schools.com\" ><item>";
            var tipo = typeof(BaseMwlItem);

            var campos = tipo.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (var c in campos)
            {
                // lista atributos do campo
                string nomeCampo = string.Empty;
                var keys = c.GetCustomAttributes(typeof(AtributoXmlBaseMwl), true);
                if (keys.Length == 1 && keys[0] is AtributoXmlBaseMwl)
                    nomeCampo = ((AtributoXmlBaseMwl)(keys[0])).NomeXml;

                if (!string.IsNullOrEmpty(nomeCampo))
                {
                    object valor = c.GetValue(this, null);
                    string valorPropriedade = string.Empty;
                    if (valor is DateTime)
                    {
                        if (nomeCampo.ToLower().Contains("time"))
                            valorPropriedade = ((DateTime)valor).ToString("hh:mm:ss");
                        else
                            valorPropriedade = ((DateTime)valor).ToString("yyyy-MM-dd");
                    }
                    else
                    {
                        valorPropriedade = valor.ToString();
                    }

                    xmlValue += string.Format("<{0}>{1}</{2}>", nomeCampo, 
                                valorPropriedade, nomeCampo);
                }
            }

            return xmlValue + "</item>";

        }




Pronto, faça o que quiser com seu XML.

Abraços
Rafael Campana


Jun 28, 2012

Windows Service Acessando Unidade de Rede

Estava com o seguinte problema:

Um serviço windows que desenvolvemos precisava acessar uma pasta localizada em uma unidade de rede, o que não estava acontecendo, mesmo passando a unidade na configuração.

Depois de alguns testes e pesquisa cheguei à seguinte conclusão.
O problema estava na forma que o drive é acessado.

É o seguinte:
O drive mapeado é específico por usuário e o serviço, por padrão , utiliza outro usuário para rodar/executar (local system), não o que está logado.

Isso quer dizer que o usuário do serviço nã conhece o driver, por exemplo "Z:", então, pesquisando, encontrei as seguintes soluções:

1ª) Mais fácil, mas que não consegui fazer funcionar:
Alterar o logon do serviço para um usuário que tenha o "Z:" mapeado corretamente, simples, não? Pena que não funcionou comigo. Mas, pode-se tentar, facinho de fazer e teve gente que falou que funciona.

2ª) que funcionou lol, Passos:
1: Parar o serviço
2: Baixar este programa: http://technet.microsoft.com/en-us/sysinternals/bb842062.aspx (utilzado para executar o cmd.exe com o usuário local system)
3: Executar o cmd.exe como administrador
4: Executar o comando "psexec -i -s cmd.exe" (abre o cmd.exe como o usuário local system)
5: Abrirá uma nova tela do cmd.exe
5: Para ter certeza que o usuário é o local system, execute o comando "whoami". O retorno deve ser "nt authority\system"
6: Agora que você sabe que o usuário é o mesmo do serviço, execute o comando de mapear unidade a partir do prompt "net use" (a sintaxe é : net use\\\/persistent:yes . Exemplo: "net use Z: \\srvdesenv-05\Teste /persistent:yes
7:Vai perdir o usuário, você coloca
8: Vai pedir senha, você coloca
9:Inicie o Serviço

Basicamente é isso ae... mas podem existir outras variáveis, principalmente de permissão.

Referências:
http://stackoverflow.com/questions/182750/how-to-map-a-network-drive-to-be-used-by-a-service

http://serverfault.com/questions/91797/windows7-the-specified-network-password-is-not-correct-when-the-password-is

Abraços
Rafael Campana

Feb 1, 2012

Erro ao conectar banco de dados "ORA-06413: Connection not open"

Boa Noite Pessoal,


Bom, semana passada eu e uma amigo (Renê) "apanhamos" muito para conectar uma aplicação com nhibernate e em um banco de dados Oracle 10g.


Como eu sou muito legal: E o problema era PARÊNTESES "( )", isso mesmo, o client do oracle para .net .


O erro que a aplicação retornava era: 




ORA-06413: Connection not open



Isso quando eu tentava conectar  uma aplicação 32 bits (x86) em uma máquina 64 bits (no caso, windows 2008 64 bits, x64) em uma base de dados oracle 10g

A solução?
Simples: Altere a pasta da aplicação para outra sem parênteses.


Exemplo:

Troque isto:


C:/Arquivos de Programs (x86)/PastaAplicacao


Por isto:




C:/Aplicacoes/PastaAplicacao  --SEM PARÊNTESES


Por hoje é só, espero ter ajudado!


Abraços

Rafael