jueves, 3 de abril de 2014

Crystal Report & Report Viewer

If you have a problem with ReportViewer you can look at this:


How to solve Report viewer issue in IIS 7 and higher versions


I recently found how to solve Report viewer issue in IIS 7 and higher versions.  Just perform the following simple steps and the issue will be solved.
i) GO to IIS manager   ( you can go it typing inetmgr in the run  or by going through Control panel)
ii) Select your virtual directly and then go to features area and click Handler mappings
iii) Click Add Handler Mappings
iv) Fill in the following information as shown below, Path =Reserved.ReportViewerWebControl.axd,
Type = Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Name= Reserved.ReportViewerWebControl.axd
v) Restart iis by typing iis reset in command prompt.
vi) Now your reports will be successfully render in Report viewer control.
Author: Umair Ashraf   umair.ashraf@gmail.com


lunes, 2 de septiembre de 2013

Windows Communication Foundation (WCF) 2 Forma

Mediante los siguientes pasos se expone como se configura un servicio web usando WCF.

  1. Crear el contrato (Interfaces) y su implementación (Clases). Lo óptimo sería crear en un proyecto exclusivo
  2. Crear el host que hará de hospedar el servicio y será puesto en IIS. Lo optimo seria tener un propio proyecto para esto.
  3. Procedemos a especificar su archivo de Configuración ( <behaviors> Y <services> ) Un EndPoint o Punto de Conexión está formado por Address, Binding y Contract ( A + B + C )
  4. Una vez que el host este iniciado y se pueda ver la exposición de su metadata de su extremo se puede crear un nuevo proyecto que será de consumidor. Para esto en el nuevo proyecto agregamos una referencia como servicio.
  5. Debemos tener un codigo donde indicará que el servicio podra o no compartir datos entre las llamadas al servicio tal como sigue:
     [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, 
     ConcurrencyMode=ConcurrencyMode.Single)]


1.   CONTRATO & IMPLEMENTACION


namespace WCFEjemplo1
{
    // NOTA: puede usar el comando "Rename" del menú "Refactorizar" para cambiar el nombre de interfaz "IServicioCliente" en el código y en el archivo de configuración a la vez.
    [ServiceContract]
    public interface IServicioCliente
    {
        [OperationContract]
        string GetData(int value);

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);

        [OperationContract]
        string MiNombre(String nombre);


        // TODO: agregue aquí sus operaciones de servicio
    }

    // Utilice un contrato de datos, como se ilustra en el ejemplo siguiente, para agregar tipos compuestos a las operaciones de servicio
    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }
}

 namespace WCFEjemplo1
{
//La siguiente linea se usa para indicar al servicio que la instancia del servicio será de tipo Single. Así podremos compartir los datos entre las llamadas al servicio

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode= ConcurrencyMode.Single)]


    public class ServicioCliente : IServicioCliente
    {

        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }


        public string MiNombre(String nombre)
        {
            return "Hola " + nombre;
        }
    }
}

ESTE PROYECTO QUEDA ASI:




2.   CREACION DEL HOST


namespace WCFConsolaHostEjemplo1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost shost = new ServiceHost(typeof(WCFEjemplo1.ServicioCliente)))
                try
                {
                    shost.Open();
                    Console.WriteLine("El servicio esta abierto");
                    Console.ReadLine();
                    shost.Close();
                }

                catch (CommunicationException ce)
                {
                    Console.Write("Una excepcion ocurrio: " + ce.Message);
                    Console.ReadLine();
                    shost.Abort();
                }
        }
    }
}


3.   CONFIGURANDO EL ARCHIVO APP.CONFIG

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="ComportamientoServicio1">
                    <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:123/WCFServicio1/def" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service behaviorConfiguration="ComportamientoServicio1" name="WCFEjemplo1.ServicioCliente">
                <endpoint address="http://localhost:123/WCFServicio1" binding="basicHttpBinding"
                    contract="WCFEjemplo1.IServicioCliente" />
                <endpoint address="http://localhost:123/WCFServicio1/mex" binding="mexHttpBinding"
                    contract="IMetadataExchange" />
            </service>
        </services>
    </system.serviceModel>
</configuration>


Quedando así:


Algunas veces en Web.Config no aparece un EndPoint porque será usada en IIS y sólo se necesitará en casos el <BEHAVIORS> o comportamiento de la clase.

En una red privada es mejor usar el enlace o protocolo binario ya que si es HTTP será un poco más lento ya que es texto.
MetaDato: Es todo el repertorio que trae el servicio que se expone. Esto permite responder al cliente quien es y que puede hacer.



Debemos tener en cuenta que existe one-way que indica que se envia mensaje al servidor sin necesidad que se obtenga respuesta de este. Esto es mejor para no esperar al servidor que tenga una punto de retorno y esto ayudaria en el trafico de la red.
El mecanismo ONEWAY hace que se manda el mensaje y no espere ya que por defecto el mecanismo del framework hace que se espere el mensaje de respuesta. Pero con oneway hace que no espere. Se desentiende de lo que recibe.




Es muy bueno usar servicios web con el fin de no tener que poner demasiada carga en los instaladores del sistema, asi solo se tendría que instalar ciertos archivos al cliente y todo se obtendria del servidor.


La idea es que no se haga cambios a la regla de negocios sino a las clases. Si hay modifcaciones ya no se modifica en el cliente (Instalador o programas instalados en el usuario) sino solo en el servicio.
Mientras no se cambie las firmas de los metodos se puede cambiar las DLL por detras.


Existes 2 patrones de comunicacion:


Request/Response: Que se debe usar generalmente y que confirme correctamente que todo llege al servidor y confirmar que se procese bien. Crea un Input & Ouput. El servidor responde


ONEWAY: Solo envia informacion y no se preocupa de nada. No se genera el Output. El servidor no responde. Sólo para métodos (void) ya que funciones necesita un retorno de valor (Ejemplo: public string nombre() {... })


Duplex: Hace una llamada al servidor y el servidor envia varias llamadas y respondiendo mensajes que no había pedido simplemente el servidor esta en potestada de mandarlo al cliente, para esto en el servidor debe tener una clase, contrato, EndPoint (Address, binding, contrac). Es como si ambos extremos fueran servidores. Para esto necesitamos otro contrato adicional.

Duplex, Este es un modelo donde se debe proporcionar en la interfaz otra interfaz asociada de devolución de llamada cuado el contrato es un contrato duplex.
El servicio principal podra llamar a los eventos del servicio asociado.


Cuando se pone en la interfaz o contrato el atributo "CallbackContract":

[ServiceContract(
    Name = "SampleContract", 
    Namespace = "Silverlight", 
    CallbackContract = typeof(IDuplexClient))]
public interface IDuplexService
{ ... 
}

Hacemos que IDuplexClient sea el contrato contrario necesario en un intercambio de mensajes bidireccionales o duplex, esto permite al cliente realizar escuchas para las llamadas de operaciones entrantes que la aplicación de servicio del lado del servidor puede enviar independientemente de la actividad del cliente. Los contratos de devolución de llamada que cuentan con operaciones unidireccionales representan llamadas del servicio que el cliente puede administrar.

DATACONTRACT


WCF Sabe como pasar tipos de datos integer, string, double, booleanos, o tipos datos primitivos de .NET etc. Pero para que pueda pasar informacion de una estructura como clase O conjunto de datos o tipos,  debemos definir la clase como <DataContract()>  y a las propiedades como <DataMember()> y tambien agregar la referencia a System.Runtime.Serializable.


Si no se pasa la etiqueta <DataMember()> WCF no sabrá como pasar ese tipo por el servicio. Con esto WCF sabe como serializar y pasara por XML y mandarlo de un lado a otro.
Si creo una clase en mi aplicacion debe marcar con DatContract para las clases y DatMember para los métodos. 


1) Creamos un nuevo proyecto de tipo consola y lo usaremos para definir las interfaces o contratos y su implementación, tambien el host y el archivo de configuración:

- Contratos e Implementación. (Archivo ChatService.vb)



using System.Collections.Generic;
using System.ServiceModel;
using System.Runtime.Serialization;
using System;


namespace ChatServiceHost
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class CChatService : IChatService
    {
        private List<String> _usuarios = new List<string>();


        private Dictionary<String, ICallBackChatService> _usuariosconectados =
            new Dictionary<String, ICallBackChatService>();


        void IChatService.IniciarSession(String nombre)
        {
           _usuarios.Add(nombre);
           _usuariosconectados.Add(nombre,OperationContext.Current.GetCallbackChannel<ICallBackChatService>());
        }


        void IChatService.CerrarSession(String nombre)
        {
            _usuarios.Remove(nombre);
            _usuariosconectados.Remove(nombre);
        }


        public void EnviarMensaje(ChatMensaje mensaje)
        {
            foreach (var usuario in _usuarios)
            {
                if (usuario != mensaje.Desde)
                {
                    _usuariosconectados[usuario].TienesUnNuevoMensaje(mensaje);

                    }

            }
        }
    }


    [ServiceContract(Name = "SampleDuplex", CallbackContract = typeof(ICallBackChatService),SessionMode = SessionMode.Required)]
    public interface IChatService
    {
        [OperationContract(IsOneWay = true)]
        void IniciarSession(String nombre);
        [OperationContract(IsOneWay = true)]
        void CerrarSession(String nombre);
        [OperationContract(IsOneWay = true)]
        void EnviarMensaje(ChatMensaje mensaje);
    }


    [ServiceContract()]
    public interface ICallBackChatService
    {
        [OperationContract(IsOneWay = true)]
        void TienesUnNuevoMensaje(ChatMensaje mensaje);
    }


    [DataContract()]
    public class ChatMensaje
    {
        private String _desde;
        private String _contenido;
        [DataMember()]
        public String Desde
        {
            get { return _desde; }
            set { _desde = value; }
        }


        [DataMember()]
        public String Contendido
        {
            get { return _contenido; }
            set { _contenido = value; }
        }
    }  
    

}




- Host. (Archivo Module1.vb)



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;




namespace ChatServiceHost
    
{
    class Program
    {
        static void Main(String[] args)
        {


            using (ServiceHost shost = new ServiceHost(typeof(CChatService)))
            {
                
                    Console.WriteLine("Se inicio el servicio");
                    shost.Open();
                    Console.WriteLine("Presiones enter para terminar");
                    Console.ReadLine();
                    shost.Close();
            }
        }
    }
}

-Archivo de configuración (app.config)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
      <section name="ChatServiceHost.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
    </sectionGroup>
  </configSections>
  <system.serviceModel>
    <bindings />
    <client />
   
    
    <services>
      <service name="ChatServiceHost.CChatService"
                 behaviorConfiguration="ServicioChatBehavior" >
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:777/ChatService"/>
            <!--AQUI USAMOS BASEADRRES PARECIDO A IIS.
            EL BASEADRRES DE IIS ES localhost:80
            -->
          </baseAddresses>
        </host>
        <endpoint address=""
                  binding="wsDualHttpBinding"
                  contract="ChatServiceHost.IChatService"/>
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServicioChatBehavior">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>



2) Creamos un segundo proyecto de tipo consola y hacemos la referencia a DataContract y referencia de tipo servicio al servicio creado en (http://localhost:777/ChatService) según el archivo de configuración de arriba, no olvidar que debe estar ejecutando el servicio.


- Cliente (program.cs)



using System;
using System.Collections.Generic;


using System.Text;
using System.ServiceModel;


namespace ChatServiceCliente
{
    class Program
    {
        static void Main(string[] args)
        {
            InstanceContext callbackInstance = new InstanceContext(new CallBackChatService());


            using (ServicioChat.SampleDuplexClient chatService = new ServicioChat.SampleDuplexClient(callbackInstance))
            {
                Console.Write("Mi nombre es: ");
                String nombre = Console.ReadLine();
                chatService.IniciarSession(nombre);
                String mensaje;


                do
                {
                    Console.Write("Yo Digo");
                    mensaje = Console.ReadLine();


                    ServicioChat.ChatMensaje chatMensaje = new ServicioChat.ChatMensaje();
                    chatMensaje.Desde = nombre;
                    chatMensaje.Contendido = mensaje;
                    chatService.EnviarMensaje(chatMensaje);


                } while (mensaje != "bye");
                chatService.CerrarSession(nombre);
            }
        }
    }
    public class CallBackChatService : ServicioChat.SampleDuplexCallback
    {


        public void TienesUnNuevoMensaje(ServicioChat.ChatMensaje mensaje)
        {
            Console.Write("");
            Console.Write(String.Format("{0} dice: {1} ", mensaje.Desde, mensaje.Contendido));
            Console.Write("******");
            Console.Write("Yo Digo");
        }
    }
}

-El archivo app.config es creado automáticamente cuando se agrega la referencia al servicio.
-Con esto ya podemos correr el servicio desde nuestro cliente.