none
Problema webservice RRS feed

  • Pergunta

  • Bom dia, sou novo em desenvolvimento em geral.
    Estou desenvolvendo um webservice, porém estou com um problema.
    Eu preciso que meu webservice mantenha um Dictionary, porém eu percebi que o Dictionary sempre anula, assim como todas as outras variáveis que eu testei.
    Eu preciso manter esse Dictionary atualizado e compartilhar para controlar os acessos.
    Eu havia feito algo parecido utilizando o banco, porém ficou lento o sistema.
    Gostaria de saber se é normal as variáveis ficarem nula, e o que posso fazer.
    Obrigado
    quarta-feira, 8 de julho de 2009 20:44

Respostas

  • Entao... eu uso sessão para esse tipo de aplicaçao mesmo...

    Mas tive uma excessao q foi que envolvia um client em java... ai eu tive que improvisar que é mais parecido com o seu caso.... nesse caso eu usei a variavel Cache:

            private string getCurrentUser(string token) {
                // Recupera o usurio do cache de sessão
                var username = (String)Context.Cache[token];
                if (String.IsNullOrEmpty(username))
                    throw new Exception("Sessão expirada!");
    
                // Atualiza o tempo de expiração da sessão
                Context.Cache.Remove(token);
                Context.Cache.Add(token, username, null, DateTime.Now.AddMinutes(SESSION_TIMEOUT), Cache.NoSlidingExpiration, CacheItemPriority.Default, new CacheItemRemovedCallback(this.OnRemoveUser));
                return username;
            }
    
    private string setCurrentUser(string username) {
                // Gerar um token não utilizado em nenhuma sessão ativa
                var token = String.Empty;
                do {
                    token = System.Guid.NewGuid().ToString("N");
                } while (Context.Cache[token] != null);
    
                // Criar uma nova sessão para o usuario informado
                Context.Cache.Add(token, username, null, DateTime.Now.AddMinutes(SESSION_TIMEOUT), Cache.NoSlidingExpiration, CacheItemPriority.Default, new CacheItemRemovedCallback(this.OnRemoveUser));
    
                // Retorna o id da sessão
                return token;
            }
    
    Nesse caso o meu WebMethod de Login retorna um token, que deve ser repassado toda vez para o webservice seja via SoapHeader ou como paramentro nos metodos.
    Outro detalhe, como eu defini um tempo de duraçao do cache, todo metodo que eu acesso presciso atualizar o tempo de expiracao:

     

    // Verifica se existe uma sesso ativa

     

    if (String.IsNullOrEmpty(this.getCurrentUser(this.Token))) {

     

    return "99 Usuario no autenticado ou sesso expirada";

    }






    Se não funciona de um jeito, tente de outro totalmente diferente ^_^
    • Marcado como Resposta kminoru quinta-feira, 9 de julho de 2009 14:26
    quinta-feira, 9 de julho de 2009 13:04
    Moderador

Todas as Respostas

  • Bem... isso vai depender do seu caso, uma forma é usar Sessão

    no seu atributo do seu metodo vc deve colocar

    [WebMethod(EnableSession=true)]

    Assim vc pode trabalhar com sessoes como numa pagina aspx normalmente....
    ah sim... se vc tiver usando um aplicativo Windows Forms tem que criar um CookieContainer para armazenar os cookies de sessao do seu web service:

    na classe program cria uma propriedade para armazenar seus cookies;

        static class Program {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main() {
                Program.Cookies = new System.Net.CookieContainer();
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
    
            public static System.Net.CookieContainer Cookies { get; set; }
        }

    e na hora de usar o service vc configura a propriedade:

    localhost.Service1 service = new localhost.Service1();
    service.CookieContainer = Program.Cookies;


    Se não funciona de um jeito, tente de outro totalmente diferente ^_^
    quarta-feira, 8 de julho de 2009 22:38
    Moderador
  • Bom dia Rui, vlw pela ajuda cara, me interessei pela Sessão, mas no webService tem métodos que não são "mapeados", que são utilizados pelo próprio webService não sendo disponível disponível, que é justamente para manipular o Dictionary, como poderei usar Sessão nesses métodos?
    Se eu colocar [WebMethod(EnableSession=true)] em todos meus métodos e colocar private, dai eu poderia usar uma variável compartilhada, mas traria alguma desvantagem para o sistema, no desempenho ou segurança?
    quinta-feira, 9 de julho de 2009 11:57
  • Olha... na verdade nunca parei para pensar nisso e sempre usei sessao nos meu metodos internos e privados sem problemas,

    Essa configuraçao eh so para os WebMetodos mesmo, por questa de seguranca.... metodos internos ja estao seguros :P

    Mas agora vc me deixou em duvida, o que acontece se eu acessar um metodo de manipula uma session em um WebMethod que nao tem sessao habilitada....

    Tem que dar uma testada nisso


    Se não funciona de um jeito, tente de outro totalmente diferente ^_^
    quinta-feira, 9 de julho de 2009 12:32
    Moderador
  • Tipo, só para vc se situar melhor quando ao meu problema...
    Quando o cliente vai acessar o webservice, ele passa o login e senha, dae o webservice pega o ip e cria um GUID, uma variável para dateTime e o login. e tudo isso fica salvo em algum lugar. O primeiro lugar testado foi no banco de dados, porém um teste que demorava 2 minutos no máximo passou a demorar 20.
    A idéia que tivemos foi de ao invés de usar o banco, usaralgum tipo de lista, no caso o Dictionary, que fica em memória mesmo, e realize as mesmas coisas.
    Pensando bem nessa troca, pode ocorrer inconsistência no Dictionary. Para controlar o acesso a manipulação do Dictionary, eu estava pensando em usar synlock, porém creio que não vá funcionar, justamente pq as variáveis ficam nulas.
    E agora josé?! :P
    quinta-feira, 9 de julho de 2009 12:52
  • Entao... eu uso sessão para esse tipo de aplicaçao mesmo...

    Mas tive uma excessao q foi que envolvia um client em java... ai eu tive que improvisar que é mais parecido com o seu caso.... nesse caso eu usei a variavel Cache:

            private string getCurrentUser(string token) {
                // Recupera o usurio do cache de sessão
                var username = (String)Context.Cache[token];
                if (String.IsNullOrEmpty(username))
                    throw new Exception("Sessão expirada!");
    
                // Atualiza o tempo de expiração da sessão
                Context.Cache.Remove(token);
                Context.Cache.Add(token, username, null, DateTime.Now.AddMinutes(SESSION_TIMEOUT), Cache.NoSlidingExpiration, CacheItemPriority.Default, new CacheItemRemovedCallback(this.OnRemoveUser));
                return username;
            }
    
    private string setCurrentUser(string username) {
                // Gerar um token não utilizado em nenhuma sessão ativa
                var token = String.Empty;
                do {
                    token = System.Guid.NewGuid().ToString("N");
                } while (Context.Cache[token] != null);
    
                // Criar uma nova sessão para o usuario informado
                Context.Cache.Add(token, username, null, DateTime.Now.AddMinutes(SESSION_TIMEOUT), Cache.NoSlidingExpiration, CacheItemPriority.Default, new CacheItemRemovedCallback(this.OnRemoveUser));
    
                // Retorna o id da sessão
                return token;
            }
    
    Nesse caso o meu WebMethod de Login retorna um token, que deve ser repassado toda vez para o webservice seja via SoapHeader ou como paramentro nos metodos.
    Outro detalhe, como eu defini um tempo de duraçao do cache, todo metodo que eu acesso presciso atualizar o tempo de expiracao:

     

    // Verifica se existe uma sesso ativa

     

    if (String.IsNullOrEmpty(this.getCurrentUser(this.Token))) {

     

    return "99 Usuario no autenticado ou sesso expirada";

    }






    Se não funciona de um jeito, tente de outro totalmente diferente ^_^
    • Marcado como Resposta kminoru quinta-feira, 9 de julho de 2009 14:26
    quinta-feira, 9 de julho de 2009 13:04
    Moderador
  • Grannnnde Rui, entendi perfeitamente o que vc fez, mas como sempre, surgiu uma dúvida que eu já havia me esquecido.
    No cliente que consome o webservice, eu crio uma "instância" do webservice. Eu estou fazendo testes simulando 8 clientes. Enfatizando o que eu havia dito, sou novato em programação,etc..
    Minha dúvida é se realmente são instâncias diferentes. Por exemplo, como meu amigo disse que eram a mesma, eu resolvi criar essa "lista" justamente para controlar o login. Mas como vi no seu código acima, me parece que não precisaria usar uma lista, e sim um objeto normal sendo que para cada cliente que consome o webservice, o objeto será usado de forma independente.
    Não sei se fui claro :D
    quinta-feira, 9 de julho de 2009 13:39
  • Acho q entendi.... na verdade vc poderia usar so um Cache com o Dictionary (Contex.Cache["Usuarios'] = new Dictionary<string, string>();) tambem funciona e tem suas utilidades...

    No caso que eu fiz, foi para poder controlar um TimeOut para cada "Sessao" independente :)

    Para vc ver, sem poder entrar em muito detalhes devido a forças maiores, esse sistema mencionado faz parte de uma integraçao de dados... no qual eu so tenho um socket com o servidor e varias requisicoes simultaneas.... entao eu tenho uma lista de dados para enviar para o servidor e uma lista de dados que recebo do servidor...

    nesse caso eu uso um item de Cache que é do tipo Dictionary.... entendeu ? mas dos dois jeitos funcionam... depende de cada caso...
    Se não funciona de um jeito, tente de outro totalmente diferente ^_^
    quinta-feira, 9 de julho de 2009 14:23
    Moderador
  • cara, vlw pela ajuda, muito obrigado mesmo :D
    Meu amigo falou pra eu usar um tal de módulo, que armazena as informações, como se fossem globais.
    muito obrigado pela força!
    quinta-feira, 9 de julho de 2009 14:26
  • o Cache faz isso e o Application.

    eh que no Cache vc pode definir um tempo de expiracao do dados, e os dados sao gravados em arquivo no servidor....

    o Application é aramazenado apenas na memoria... se vc reiniciar o servidor os dados se apagam

    Application é bom para uma quantidade pequena de dados por ter um acesso rapido

    o Cache é bom para um acesso a uma quantidade grande de dados e tem um acesso mais lento

    ^^ como disse cada caso é um caso... normalmente é melhor usar um Application com um Dictionary para controla a sessoes mesmo, mas eu preferi usar o Cache por que é mais facil de implementar um controle de tempo para expirar a sessão :P
    Se não funciona de um jeito, tente de outro totalmente diferente ^_^
    quinta-feira, 9 de julho de 2009 14:31
    Moderador
  • Tipo, a minha aplicação é pequena, serão uns 20 clientes. Para controlar o tempo foi simplex, só pegar a diferença do tempo usando o DateDiff
    :d
    mas vlw pela ajuda :D
    quinta-feira, 9 de julho de 2009 14:40
  • Ah mas ia vc vai ter que digitar uma linha de codigo a mais U.U (sim eu tmb sou preguiçoso)  kkkkkkkkkkkkkkkkkkk


    Mas a ideia é essa mesmo, se vc ta diposto a fazer o controle de sessao entao usa o Application mesmo... so nao esquece de usar o Application.Lock() para evitar de coincidir 2 usarios gravando ao mesmo tempo ok ?
    Se não funciona de um jeito, tente de outro totalmente diferente ^_^
    quinta-feira, 9 de julho de 2009 16:18
    Moderador
  • como assim lock?
    eu terei que fazer esse método ou já tem?
    eu não consegui usar...
    E tipo...meus clientes são enumerados, ou seja, o cliente 1 terá key 1, o 2 a key 2 e assim por diante, realmente é necessário eu controlar a sincronização?
    quinta-feira, 9 de julho de 2009 17:10
  • o Application ja tem os metodos Lock() e Unlock();

    eh que tem coisas q é melhor nao arrinscar... por exemplo quando vc faz

    Application["Numero"] = (Application["Numero"] ) + 1;

    pode acontecer de 2 usuario diparam o metodo ao mesmo tempo o que aconteceria isso aqui

    valor atual 3,
    usuario A acassa: 3 + 1 = 4

    valor atual 4
    usuario B e C acessam ao mesmo tempo (4 + 1) - pq para os 2 o valor era 4
    valor atual 5 (errado... deveria ser 6)

    para evitar esse tipo de problema... sempre q for gravar um dado na aplication faz assim

    Application.Lock()
    try {
         Application["Chave"] = valor;"
    } finally {
        Application.Unlock();
    }


    assim se um usuario tentar acessar a variavel applicatio que tiver em uso por outro, o framework vai gerar uma lista... algo como uma Transaction no Banco de dados


    Se não funciona de um jeito, tente de outro totalmente diferente ^_^
    quinta-feira, 9 de julho de 2009 18:05
    Moderador
  • viu cara, eu publiquei meu webservice em um servidor FTP, mas não funcinou lá, como faço pra debugar o webservice de lá?
    ou o que pode estar dando erro?
    quinta-feira, 9 de julho de 2009 18:32
  • vc sabe a versao do IIS do servidor, se for o IIS 6 para cima vc tem que dar um acesso numa opçao do IIS que agora nao lembro de cor... se for o 7 eu nunca usei U.U e se for o 5... nas propriedades do site tem uma aba para vc configura a versao do .NET que vc esta usando...

    Sobre o debug remoto, aconcelho vc abrir outro post sobre o assunto, acho q vai ser mais rapido para vc ja que agora to meio enrolado :S


    Se não funciona de um jeito, tente de outro totalmente diferente ^_^
    quinta-feira, 9 de julho de 2009 20:22
    Moderador
  • Cara, depois de alguns erros, cheguei em um que eu não consigo sair.
    Deu erro de parse na linha 1 do arquivo asmx.vb

    Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.

    Parser Error Message: Could not create type 'WebService.WebService'.

    Source Error:

    Line 1:  <%@ WebService Language="vb" CodeBehind="WebService.asmx.vb" Class="WebService.WebService" %>
    quinta-feira, 9 de julho de 2009 20:27
  • Uhm... meu toma cuidado quando usar nomes de classes que ja sao usados pelo .NET

    experimenta cria um Webservice novo com outro nome...

    pq parece q vc tem um Namesapce chamado WebService com uma classe WebSerice que herda uma classe WebService... meio confuso isso :P, mas tudo bem... so por isso nao deveria dar erro

    se puder por a declaracao da classe do arquivo WebService.asmx.vb ai (alias.. vc copiou o arquivo WebService.asmx.vb para o servidor ?) fica mais facil... so a parte que vai dos "using" ate o public class WebService...


    Se não funciona de um jeito, tente de outro totalmente diferente ^_^
    quinta-feira, 9 de julho de 2009 20:37
    Moderador
  • cara, consegui publicar. Melhor dizendo...publicaram pra mim..
    mauhauahuahua
    vlw pela força!
    quinta-feira, 9 de julho de 2009 20:45