Welcome to 3Dev Blogs Sign in | Join | Help
<September 2008>
SuMoTuWeThFrSa
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

Navigation

Syndication

JSON en Ajax

De regreso hoy lunes de Arequipa donde estuve dictando un curso el fin de semana. Por coincidencia esta semana que paso tanto este curso como otro en un cliente he tocado los temas de ASP .NET Ajax.

Ahora cuando comienzo el curso y hablo de que cuando se desarrolla con Ajax en ASP .NET se debe evaluar el rendimiento para buscar la forma para tener una pagina eficiente vienen los comentarios acerca de los problemas que han tenido con sobrecarga en las paginas. Ciertamente el UpdatePanel facilita mucho el trabajo pero hay varias formas de lograr usar Ajax ademas del UpdatePanel y que en ocasiones es ideal.

Entonces ahora empezamos el curso hablando justamente del enfoque del lado del cliente con ASP .NET Ajax. Ajax nos permite invocar funcionalidades de servidor sin necesidad de crear servicios web con los métodos de página (Page Methods). El objetivo es permitirnos llamar a métodos estáticos de cualquier página (.aspx) desde el cliente utilizando Javascript  sin complicarnos mucho la vida y de una forma mas eficiente.

En principio Ajax emite JSON por defecto, esto se puede configurar a traves del atributo

[ScriptService], configurandolo podriamos definir la forma de la llamada a traves de POST o GET y la forma de la serializacion, por ejemplo

[ScriptMethod(ResponseFormat=ResponseFormat.Json )]

[WebMethod]

public int LeerCantidadEmpleados(string departmento)

{

System.Threading.Thread.Sleep(2000);

return RecursosHumanos.LeerCantidad(departmento);

}

Donde este metodo ofrece una serializacion JSON, la otra alternativa podria ser XML.

A continuacion voy a mostrar como invocar directamente un servicio web desde una pagian ASP .NET pero usando elementos HTML con el ScriptManager pero sin usar controles del lado del servidor para mejorar el rendimiento de la pagina al no usar UpdatePanel:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="EnfoqueDelCliente.aspx.cs" Inherits="EnfoqueDelCliente" %>

<html>

<body>

<form id="form1" runat="server">

<asp:ScriptManager ID="ScriptManager1" runat="server">

<Services>

<asp:ServiceReference Path="Servicio.asmx" />

</Services>

</asp:ScriptManager>

<h2>Busqueda de Empleados</h2>

<div>

<select id="Departamentos" size="5">

<option value="Ingenieria">Ingenieria</option>

<option value="HR">Recursos Humanos</option>

<option value="Ventas">Ventas</option>

<option value="Marketing">Marketing</option>

</select>

</div>

<br />

<div>

<span id="Resultado"></span>

<span id="loading" style="display:none;">

<img src="images/indicator.gif" alt="" />

&nbsp;&nbsp;Loading ...

</span>

</div>

<script type="text/javascript">

<!--

var departments = null;

Sys.Application.add_load(page_load);

Sys.Application.add_unload(page_unload);

function page_load(sender, e){

departamentos = $get("Departamentos");

$addHandler(departamentos, "change", departamentos_onchange);

}

function page_unload(sender, e){

$removeHandler(departamentos, "change", departamentos_onchange);

}

function departamentos_onchange(sender, e){

$get("Resultado").innerHTML = "";

$get("loading").style.display = "block";

var selectedValue = departamentos.value;

Servicio.LeerCantidadEmpleados(selectedValue, onSuccess);

}

function onSuccess(result){

$get("loading").style.display = "none";

$get("Resultado").innerHTML = "Cantidad Empleados: " + result;

}

//-->

</script>

</form>

</body>

</html>

 

En esta seccion se referencia al servicio web:

<asp:ScriptManager ID="ScriptManager1" runat="server">

<Services>

<asp:ServiceReference Path="Servicio.asmx" />

</Services>

En este metodo JavaScript se llama al metodo LeerCantidadEmpleado del servicio web pasandole el elemento seleccionado de la lista y derivando la ejecucion al metodo onSuccess, que es donde se recibe el resultado del servidor y se procesa en el cliente:

function departamentos_onchange(sender, e){

$get("Resultado").innerHTML = "";

$get("loading").style.display = "block";

var selectedValue = departamentos.value;

Servicio.LeerCantidadEmpleados(selectedValue, onSuccess);

}

Metodo donde se procesa el resultado:

function onSuccess(result){

$get("loading").style.display = "none";

$get("Resultado").innerHTML = "Cantidad Empleados: " + result;

}

Ahora se puede lograr lo mismo con el atributo PageMethods del ScriptManager de la siguiente manera:

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods=true>

</asp:ScriptManager>

Y el metodo JavaScritp cambia de la siguiente manera:

function departamentos_onchange(sender, e){

$get("Resultado").innerHTML = "";

$get("loading").style.display = "block";

var selectedValue = departamentos.value;

PageMethods.LeerCantidadEmpleados(selectedValue, onSuccess);

}

Ademas el metodo invocado se escribe en la misma pagina ASP .NET de la siguiente manera:

[WebMethod]

public static int LeerCantidadEmpleados(string departmento)

{

System.Threading.Thread.Sleep(2000);

return RecursosHumanos.LeerCantidad(departmento);

}

En este caso no es necesario que sea un servicio Web pero si un metodo estatico. Estas dos formas son alternativas a usar un UpdatePanel y demuestran una forma eficiente de usar Ajax en ASP .NET.

Otra forma habitual de hacer esta invocacion seria usando JQuery que brinda caracteristicas adicionales como son capacidad de invocar al metodo o al servicio desde otra pagina, una limitante que en este caso se muestra en ASP .NET Ajax.

posted Tuesday, August 05, 2008 12:32 AM by jfrancia | 2 Comments
Attachment(s): EnfoqueDelCliente.zip

WCF REST Services

Operaciones WCF para la Web

Estas operaciones se exponen a traves de URIs, los mensajes se transmiten sin la sobrecarga de SOAP, los parametros se pasan usando HTTP, el formato de los datos puede ser JSON o POX. WCF provee WebHttpBinding binding para soportar estas caracteristicas. Este binding tiene dos elementos. El primero es un nuevo encoder llamado WebMessageEncodingBindingElement, el cual permite seleccionar entre JSON o POX. El segundo elemento es un elemento binding de transporte basado en HttpTransportBindingElement o HttpsTransportBindingElement. El HttpsTransportBindingElement es usado para seguridad a nivel de transporte.

Para el binding WebHttpBinding pueden ser usados dos behaviors. El WebHttpBehavior y el WebScriptEnablingBehavior. El WebScriptEnablingBehavior behavior  se usara para  AJAX y JSON. El WebHttpBehavior behaviorse usa para formatear los mensajes usando JSON o XML. El valor por defecto es usar XML.

Ejemplo:

using System;
using System.ServiceModel;
using System.ServiceModel.Web;

[ServiceContract]
public interface IMensaje
{
    [OperationContract]
    [WebGet]
    string Responder(string mensaje);
}

using System;
using System.ServiceModel;

public class ServicioMensaje : IMensaje

{
    #region IMensaje Members

    public string Responder(string mensaje)
    {

        return mensaje;
    }

    #endregion
}

 

<system.serviceModel>
  <services>
    <service name="ServicioMensaje">
      <endpoint address=""
                behaviorConfiguration="WebBehavior"
                binding="webHttpBinding" contract="IMensaje"/>
    </service>
  </services>
  <behaviors>
    <endpointBehaviors>
      <behavior name="WebBehavior">
        <webHttp />
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>

 

POX y REST se basan ambos en invocaciones a traves de URLs para llamar a los metodos. Donde tienen diferencias es en la forma como son definidos estos URLs, y que verbos HTTP son usados para invocar las operaciones en cada URL.

WebGet Y WebInvoke

Los servicios pueden ser expuestos usando WebHttpBinding binding, usando ya sea los atributos WebGet o WebInvoke. Cada atributo especifica el verbo HTTP, el formato del mensaje y el estilo del cuerpo que se requiere para exponer una operacion.

WebGet

Este atributo exponer el verbo GET. Get tiene ventajas sobre los verbos HTTP. Primero, el endpoint puede ser accesado directamente via un navegador ingresando el URL del servicio en la barra de direcciones. Los parametros pueden ser enviados dentro del URI como query strings o dentro del URI. Este atributo debe ser usado para recuperacion.

WebInvoke

Este atributo expone los servicios usando los verbos HTTP como POST, PUT y DELETE. Por defecto es POST, pero puede ser modificado configurando la propiedad "Method" del atributo. Estas operaciones sirven para modificar recursos, por lo tanto este atributo debe ser usado para realizar modificaciones a recurso.

using System;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace EssentialWCF
{
    [ServiceContract]
    public class ServicioCliente
    {
        [OperationContract]
        [WebGet(UriTemplate="/cliente/{id}")]
        public Customer LeerCliente(int id)
        {
            Customer customer = null;

            // Leer cliente de la base de datos
            return customer;
        }

        [OperationContract]
        [WebInvoke(Method = "PUT", UriTemplate = "/cliente/{id}")]
        public void EnviarCliente(int id, Customer customer)
        {
            // Grabar en la base de datos
        }

        [OperationContract]
        [WebInvoke(Method = "DELETE", UriTemplate = "/cliente/{id}")]
        public void EliminarCliente(int id)
        {
            // Grabar en la base de datos

        }
    }
}

posted Thursday, June 26, 2008 12:28 AM by jfrancia | 2 Comments

Seguridad en REST

Siendo casi la 1 am aqui en Lima continuo escribiendo las preguntas que he acumulado.

Una pregunta sobre REST es como implementar la seguridad.

La seguridad en REST hoy en dia esta limitada a la autenticacion HTTP, los que llaman pueden usar Basic, Digest, Windows o credenciales de certificados para autentificar cada llamada. Los cookies HTTP pueden ser asignados despues que quien llama es identificado usando la autentificacion de ASP .NET o despues de completada la autentificacion HTTP.

Al usar WebHttpBinding se puede habilitar la autentificacion para un endpoint al habilitar uno de dos modos de seguridad: Transport o TransportCredentialOnly Transport requiere SSL, mientras que TransportCredentialOnly envia las credenciales sin SLL. En cualquier caso  la eleccion de la credencial esta definida por los valores de HttpClientCredentialType

Aqui estan los posibles valores:

http://msdn.microsoft.com/en-us/library/system.servicemodel.httpclientcredentialtype.aspx

 

Una alternativa menos atractiva es proteger los servicios REST usando la autentificacion ASP .NET. Lo cual significa habilitar el modo de compatibilidad ASP .NET para el servicio.

 

posted Wednesday, June 25, 2008 1:48 AM by jfrancia | 0 Comments

Mixing REST and SOAP parte II

Finalmente pense que Jonathan Chavez estaria contento por mi respuesta y me sale con otra pregunta:

"

solo tengo los asmx

Jona says:

el contrato y mi implementation

Jona says:

no es como cuando lo hacia en consola

Jona says:

de iniciar el host y todo eso

" (Texto reproducidos con su consentimiento)

 

Es simple la respuesta y aqui va:

 

Lo mismo se aplica cuando se usa WebServiceHostFactory para los endpoints .svc

En algo que seria como esto:

 

<%ServiceHost Language="C#" 
    Debug="true" 
    Service="TimeTrakkerServicio" 
    CodeBehind="~/App_Code/TimeTrakkerClass.cs" 
    Factory="System.ServiceModel.
             Activation.
             WebServiceHostFactory"
%>

posted Wednesday, June 25, 2008 1:35 AM by jfrancia | 0 Comments

Mixing REST and SOAP

A proposito del TechEd 2008, estuve invitado como parte del equipo de Arquitectura en el "Ask The Experts", fue un evento fabuloso, y algo que quedo en el tintero fue el uso de WCF en .NET 3.5. De alli en mas inmediatamente gracias al apoyo de mis alumnos en el curso de Taller que dicto en USIL (www.usil.edu.pe)  empezamos a implementar muchas de las caracteristicas. Una de ellas es REST, tambien con algo de JQuery (para mejorar Ajax) y claro esta JSON. Pero un reto y tarea pendiente que tenia era implementar servicios usando DuplexBinding, una sugerencia que recibi de Shy Cohen de Microsoft sobre una pregunta de arquitecturas basadas den Firewall NAT. Bueno espero que puedan tener todo listo para la presentacion en dos semanas :)

De este experimento recibi una consulta interesante de uno de mis alumnos (Jonathan Chavez) sobre el uso de REST. Nuestro proyecto considera el uso de REST con WCF, antes de eso habiamos trabajado bajo el modelo de la fabrica de Software para modelar los contratos. La pregunta es: Como mezclar REST y SOAP?, es decir de que manera se pueden exponer los servicios sin tener que programar o modelar dos veces el servicio.

Que sucede si queremos alojar el mismo servicio WCF usando SOAP y REST?. De hecho un solo contrato de servicio y su implementacion pueden manejar ambos tipos de "requests".

- REST se basa en un modelo de servicio que permite mapear a un URL una operacion particular, SOAP se basa en un "action header" dentro del mensaje.

- Los mensaje REST pueden ser formateados como XML o JSON, los mensajes SOAP pueden ser serializados como binarios, XML o MTOM

Al decorar los contratos con WebGetAttribute o WebInvokeAttribute se puede especificar el UriTemplate para el mapeo de las operaciones a los URLs. Los mismos atributos permiten definir la serializacion JSON o XML.

Estos atributos son ignorados a menos que se habilite el WebHttpBEhavior para un "endpoint". Entonces si se expone dos endpoints para el mismo contrato, se puede configurar uno para REST y el otro para SOAP. La direccion para cada uno debe ser unica, como por ejemplo:

<services>

<service name="ServicioCliente">

<endpoint address="http://localhost:8000/ServicioCliente/REST" binding="webHttpBinding" contract="Contrato.IServicioCliente"/>

<endpoint address="http://localhost:8000/ServicioCliente/SOAP" binding="wsHttpBinding" contract="Contrato.IServicioCliente"/>

</service>

</services>

La configuracion usa WebHttpBinding para /Rest y WsHttpBinding para Soap.

- Se pueden exponer ambos endpoint usando WebService-Host en lugar de ServiceHost. El siguiente codigo muestra como en un "self-host" (una aplicacion de consola, o windows, o un servicio windows, etc.) se puede hacer.

WebServiceHost ohost=new WebServiceHost(typeof(Servicios.ServicioCliente));

ohost.Open();

 

posted Wednesday, June 25, 2008 12:59 AM by jfrancia | 0 Comments

Fast page loading by moving ASP.NET AJAX scripts after visible content

Otro problema frecuente con Ajax en ASP .NET es el tiempo que demora en cargar por primera vez la pagina. Muchas veces esto puede llegar a ser un problema.

Encontre un articulo

http://msmvps.com/blogs/omar/archive/2008/04/06/fast-page-loading-by-postponing-asp-net-ajax-scripts-after-content.aspx

donde muestra como hacer que la carga de los Scripts de Ajax se haga al final de la pagina lo que permite tener una experiencia de usuario que no se ve afectada por los scripts. Este articulo lleva a una aplicacion

www.dropthings.com

Y donde los autores ademas hacen referencia a un libro que es bastante recomendable.

Building a Web 2.0 Portal with ASP.NET 3.5

http://oreilly.com/catalog/9780596510503/

Bastante codigo y muchos tips.

Joel

 

 

posted Tuesday, June 10, 2008 7:33 PM by jfrancia | 0 Comments

Why ASP.NET AJAX UpdatePanels are dangerous?

http://encosia.com/2007/07/11/why-aspnet-ajax-updatepanels-are-dangerous/

He recibido varias consultas acerca de como optimizar Ajax. Aqui se muestra algunos tips importantes que permiten optimizar el uso de Ajax en .NET.

Por ejemplo hay una nota que puedo resaltarles:

Using JSON, the entire HTTP round trip is 24 bytes, as compared to 872 bytes for the UpdatePanel. That’s roughly a 4,000% improvement, which will only continue to increase with the complexity of the page.

Joel

 

posted Tuesday, June 10, 2008 7:27 PM by jfrancia | 0 Comments

SilverLight en el sitio de 3Dev

Quisiera compartir con ustedes unas demos que hemos puesto en nuestra pagina de SilverLight

En esta URL pueden encontrar un visor hecho con SilverLight

http://www.3devnet.com/servicios.aspx

En nuestra zona de descarga hay varias demos que pueden descargar. El codigo fuente esta alli para descargar.

http://www.3devnet.com/descargas.aspx

En estas direcciones pueden ver las demos directamente

http://www.3devnet.com/silverlight/playernormal/
http://www.3devnet.com/silverlight/banner/sample/

 

Joel

posted Saturday, May 31, 2008 6:38 PM by jfrancia | 0 Comments

Base de datos de la demo de Eventos con .NET Remoting

Base de datos de la demo de Eventos con .NET Remoting. Por favor me envian un correo a jfrancia@3devnet.com para enviarles la BD.

 

Joel

posted Thursday, May 01, 2008 8:32 PM by jfrancia | 0 Comments
Attachment(s): DemoPerson_bak

Eventos con .NET Remoting Parte III

Proyecto Cliente

Form1.cs

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting.Channels.Tcp;

using CommonAssembly;

using Entidades;

namespace DemosEventosRemoting

{

public partial class Form1 : Form

{

private string sucursal="";

public Form1(string _sucursal)

{

InitializeComponent();

sucursal = _sucursal;

this.Text = sucursal;

}

IOrder _orderObject;

private void Form1_Load(object sender, EventArgs e)

{

RemotingConfiguration.Configure("DemosEventosRemoting.exe.config",false);

WellKnownClientTypeEntry[] entry = RemotingConfiguration.GetRegisteredWellKnownClientTypes();

_orderObject = (IOrder)Activator.GetObject( entry[0].ObjectType

,entry[0].ObjectUrl);

AgregarEventHandler o = new AgregarEventHandler(refrescarLista);

_orderObject.AddOnAgregarEvent(o);

List<Person> prs = _orderObject.getPersons();

bindingSource1.DataSource = prs;

}

Person person;

public void refrescarLista(object o, ArgumentosEventArgs e)

{

string s = e.Sucursal;

if (s == sucursal)

{

person = e.Person;

this.BeginInvoke(new MethodInvoker(delegate()

{

bindingSource1.Add(person);

}));

}

}

//private void Pintar()

//{

// bindingSource1.Add(person);

//}

private void btnOK_Click(object sender, EventArgs e)

{

Form2 fr = new Form2(_orderObject, sucursal);

fr.Show();

}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)

{

AgregarEventHandler o = new AgregarEventHandler(refrescarLista);

_orderObject.AddOnRemoveEvent(o);

}

}

}

 

Form2.cs

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using CommonAssembly;

using Entidades;

namespace DemosEventosRemoting

{

public partial class Form2 : Form

{

public Form2()

{

InitializeComponent();

}

IOrder _orderObject;

string sucursal = "";

public Form2(IOrder orderObject,string _sucursal)

{

_orderObject = orderObject;

sucursal = _sucursal;

InitializeComponent();

}

private void button1_Click(object sender, EventArgs e)

{

Person p = new Person();

p.Nombre = textBox1.Text;

p.Apellido = textBox2.Text;

p.Edad = Convert.ToInt32(textBox3.Text);

p.Direccion = textBox4.Text;

_orderObject.Insertar(p,sucursal);

}

}

}

 

Formulario SetSucursal

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

namespace DemosEventosRemoting

{

public partial class SetSucursal : Form

{

public SetSucursal()

{

InitializeComponent();

}

private void button1_Click(object sender, EventArgs e)

{

string s = comboBox1.Text;

Form1 fr = new Form1(s);

fr.Show();

}

}

}

 

Program.cs

 

using System;

using System.Collections.Generic;

using System.Windows.Forms;

namespace DemosEventosRemoting

{

static class Program

{

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main()

{

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false);

Application.Run(new SetSucursal());

}

}

}

posted Thursday, May 01, 2008 8:17 PM by jfrancia | 0 Comments

Eventos con .NET Remoting Parte II

Proyecto ServerP

ServerP.cs

using System;

using System.Collections.Generic;

using System.Text;

using System.Runtime.Remoting;

 

namespace ServerP

{

class Program

{

static void Main(string[] args)

{

RemotingConfiguration.Configure("ServerP.exe.config", false);

Console.WriteLine("Hello from the Server");

Console.ReadLine();

}

}

}

 

ServerP.exe.config

 

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<system.runtime.remoting>

<application>

<channels>

<channel port="6000" displayName="CakeServerChannel" ref="tcp">

<serverProviders>

<formatter ref="binary" typeFilterLevel="Full" />

</serverProviders>

<clientProviders>

<formatter ref="binary" />

</clientProviders>

</channel>

</channels>

<service>

<wellknown type="OrdenBL.Orden, OrdenBL"

objectUri="Orden" mode="Singleton"/>

</service>

</application>

</system.runtime.remoting>

</configuration>

 

Proyecto Entidades

Person.cs

using System;

using System.Collections.Generic;

using System.Text;

namespace Entidades

{

[Serializable]

public class Person

{

private string nombre;

public string Nombre

{

get { return nombre; }

set { nombre = value; }

}

private string apellido;

public string Apellido

{

get { return apellido; }

set { apellido = value; }

}

private int edad;

public int Edad

{

get { return edad; }

set { edad = value; }

}

private string direccion;

public string Direccion

{

get { return direccion; }

set { direccion = value; }

}

}

}

 

Proyecto DAPerson, disculpen la cadena de conexion

using System;

using System.Collections.Generic;

using System.Text;

using System.Data;

using System.Data.SqlClient;

using Entidades;

namespace DAPerson

{

public class DALPerson

{

public List<Person> GetDAPersons()

{

string cn = @"Data Source=.\sql2005;Initial Catalog=DemoPerson;Integrated Security=True;Pooling=False";

List<Person> persons = new List<Person>();

using (SqlConnection cnn = new SqlConnection(cn))

{

using (SqlCommand cmd = new SqlCommand("getPersons", cnn))

{

cmd.CommandType = CommandType.StoredProcedure;

cnn.Open();

SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleResult | CommandBehavior.CloseConnection);

while (reader.Read())

{

Person pp = new Person();

pp.Nombre = reader["Nombre"].ToString();

pp.Apellido = reader["Apellido"].ToString();

pp.Edad = Convert.ToInt32(reader["Edad"]);

pp.Direccion = reader["Direccion"].ToString();

persons.Add(pp);

}

 

}

}

return persons;

}

public void SetDAPerson(Person person)

{

string cn = @"Data Source=.\sql2005;Initial Catalog=DemoPerson;Integrated Security=True;Pooling=False";

using (SqlConnection cnn = new SqlConnection(cn))

{

using (SqlCommand cmd = new SqlCommand("setPerson", cnn))

{

cmd.CommandType = CommandType.StoredProcedure;

cnn.Open();

cmd.Parameters.Add("@Nombre", SqlDbType.VarChar).Value = person.Nombre;

cmd.Parameters.Add("@Apellido", SqlDbType.VarChar).Value = person.Apellido;

cmd.Parameters.Add("@Edad", SqlDbType.Int).Value = person.Edad;

cmd.Parameters.Add("@Direccion", SqlDbType.VarChar).Value = person.Direccion;

cmd.ExecuteNonQuery();

}

}

}

}

}

posted Thursday, May 01, 2008 8:10 PM by jfrancia | 0 Comments

Eventos con .NET Remoting

Hola, nuevamente regresando al blog, aqui invito a compartir una demo sobre como implementar eventos con .NET Remoting, lo hare en dos envios, y luego pasare a comentar el codigo.

 

Proyecto CommonAssembly

IOrder.cs

using System;

using System.Collections.Generic;

using System.Text;

using Entidades;

namespace CommonAssembly

{

public interface IOrder

{

void Insertar(Person person,string sucursal);

void AddOnAgregarEvent(AgregarEventHandler handler);

void AddOnRemoveEvent(AgregarEventHandler handler);

List<Person> getPersons();

string getSucursalEnvio(string suc);

}

}

 

ArgumentosEventArgs.cs

 

using System;

using System.Collections.Generic;

using System.Text;

using Entidades;

namespace CommonAssembly

{

public delegate void AgregarEventHandler(object o, ArgumentosEventArgs e);

[Serializable]

public class ArgumentosEventArgs:EventArgs

{

private Entidades.Person person;

private string sucursal;

public string Sucursal

{

get { return sucursal; }

}

public Entidades.Person Person

{

get { return person; }

}

public ArgumentosEventArgs(Entidades.Person m_person, string _sucursal)

{

person = m_person;

sucursal = _sucursal;

}

}

}

Proyecto OrdenBL

OrdenBL.cs

using System;

using System.Collections.Generic;

using System.Text;

using CommonAssembly;

using Entidades;

using DAPerson;

namespace OrdenBL

{

public class Orden : MarshalByRefObject, IOrder

{

public event AgregarEventHandler AgregarEvento;

#region IOrder Members

public void Insertar(Person person,string sucursal)

{

DALPerson dal = new DALPerson();

dal.SetDAPerson(person);

List<Person> pers = dal.GetDAPersons();

ArgumentosEventArgs e = new ArgumentosEventArgs(person, sucursal);

OnAgregarEvento(e);

}

public void AddOnAgregarEvent(AgregarEventHandler handler)

{

AgregarEvento += handler;

}

#endregion

private void OnAgregarEvento(ArgumentosEventArgs Argumentos)

{

if (AgregarEvento != null)

AgregarEvento(this, Argumentos);

}

#region IOrder Members

 

public List<Person> getPersons()

{

return new DALPerson().GetDAPersons();

}

#endregion

#region IOrder Members

 

public void AddOnRemoveEvent(AgregarEventHandler handler)

{

AgregarEvento -= handler;

}

#endregion

public override object InitializeLifetimeService()

{

return null;

}

#region IOrder Members

 

public string getSucursalEnvio(string suc)

{

return suc;

}

#endregion

}

}

posted Thursday, May 01, 2008 7:59 PM by jfrancia | 0 Comments

CTP Enterprise Library 3.0

http://www.codeplex.com/entlib/Release/ProjectReleases.aspx?ReleaseId=1368

 

Joel

posted Sunday, December 24, 2006 2:17 PM by jfrancia | 0 Comments

CREACIÓN DEL MODELO DE OBJETOS DE UNA APLICACIÓN WINDOWS FORMS

 

 

 

 

 

 

 

 

 

 

 

Hands-On Lab

PROGRAMACION ORIENTADA

A OBJETOS

Creando un Diagrama

de Clases en un Aplicación

Windows Forms

 

 

 

 

                 

 

 

LABORATORIO: HACIENDO USO DE DIAGRAMAS DE CLASE EN LA CREACION DE UN APLICACIÓN WINDOWS FORMS

 

Este laboratorio haremos uso de una de las nuevas características de Visual Studio 2005 que permite al desarrollador hacer uso de diagramas que permitan documentar así como modificar el código de manera visual.

 

Esta proyecto será nuestro inicio para la creación de una solución escalable haciendo uso Visual Studio 2005 y SQL Server 2005.

 

Tiempo estimado: 30 minutos


EJERCICIO: CREACIÓN DEL MODELO DE OBJETOS DE UNA APLICACIÓN WINDOWS FORMS

 

Objetivo

  • Aprender a utilizar el diseñador de clase de Visual Studio 2005.
  • Diseñar el modelo de objetos de la capa de presentación.
  • Hacer uso de los conceptos de orientación a objetos.

 

Escenario

En el siguiente ejercicio va a crear el diagrama de clases de nuestra aplicación base y aplicaremos los conceptos de orientación a objetos.

En este laboratorio solo implementaremos los métodos y funciones de nuestras clases en el siguiente laboratorio procederemos a crear la interfaz grafica de nuestros formularios.

 

Figura 1. Diagrama de Clases

 

Paso 1: Crear un nuevo proyecto Windows Application desde Microsoft Visual Studio .NET 2005.

 

  1. Abrir Visual Studio .NET 2005.
  2. En el menú File/New y click en Project…
  3. En la ventana de diálogo New Project, en el panel izquierdo Project Types expanda el nodo Visual Basic y luego seleccione el nodo Windows.
  4. En la lista Templates, click en Windows Application.
  5. En Name tipear AppDemo
  6. Guardar en la ruta C:\ 3Dev\
  7. Click en OK.

 

Paso 2: Configurando las propiedades del Proyecto

 

  1. En la ventana del Solution Explorer, click derecho sobre AppDemo, click en Properties,
  2. Se nos mostrara la pantalla con las opciones de configuración del Proyecto, el primer Tab: Application (figura 2)
  3. En la caja de Texto Root NameSpace  borramos el valor colocado por defecto (el nombre de la Aplicación). Este valor pone por defecto un Namespace a todas las clases creadas en nuestro proyecto  lo que podría traer cierta confusión al hacer referencias a estas, si se desconoce la función que tiene esta propiedad.

 


 

 

Figura 2: Ventana de Propiedades del Proyecto

 

Paso 3: Diseñar los formularios Base de nuestro Aplicativo.

 

  1. En el Solution Explorer, click derecho sobre AppDemo, click en Add, click en New Folder y tipeamos Base (Carpeta que contendrá nuestros formularios base).

 

  1. En el Solution Explorer, click derecho sobre la carpeta Base, click en Add, click en Windows Form y le ponemos por Nombre FormBaseBase.vb este formulario será nuestro clase Base del cual hereden los demás formulario Base que crearemos.

 

 

  1. Procederemos a implementar el código dentro de nuestro formulario  FormBaseBase, presionamos F7 para ver el código del formulario asociado a nuestro formulario. Procederemos a especificar el NameSpace asociado al formulario, como se muestra a continuación.

 

 

Namespace _3Dev.AppDemo.Base

 

    Public Class FormBaseBase

 

    End Class

 

End Namespace

 

Así también debemos colocar el código  en la clase parcial de nuestro formulario sino cuando queramos ver el diseñador de nuestra pantalla nos saldrá un error como el que se muestra a continuación:

 

Figura 3

 

Para esto procedemos en expandir el formulario FormBaseBase, en el Solution Explorer, click sobre FormBaseBase, y expandimos para ver el detalle y damos doubleclick sobre el archivo FormBaseBase.Designer.vb y adicionamos el mismo NameSpace puesto en el archivo FormBaseBase.vb.

 

 

 

  1. Ahora adicionaremos el código necesario a nuestro formulario Base, escriba en siguiente código a FormBaseBase.vb, en el Solution Explorer, click sobre FormBaseBase, y presionamos F7 para que se muestre el código del formulario, seguidamente escribimos lo siguiente.

 

 

Namespace _3Dev.AppDemo.Base

 

    Public Class FormBaseBase

 

       ' Definimos Propiedades del formulario

        Private _idForm As String = String.Empty

        Private _tituloForm As String = String.Empty

        Protected ds As DataSet = Nothing

 

        Protected Property IdForm() As String

            Get

                Return _idForm

            End Get

            Set(ByVal value As String)

                _idForm = value

            End Set

        End Property

 

        Protected Property TituloForm() As String

            Get

                Return _tituloForm

            End Get

            Set(ByVal value As String)

                _tituloForm = value

            End Set

        End Property

 

        Protected Sub ControlAcceso(ByVal IdForm As String)

            ' Cumple la siguiente funcionalidad

            ' 1° Permitir o no el acceso al formulario

            ' 2° Controlar el habilitar o no de acuerdo al      

            '    acceso del usuario a los botones y/o opciones

            '    del formulario

        End Sub

 

    End Class

 

End Namespace

 

 

 

  1. Procedemos a Grabar y construimos el Proyecto, Menú Build, click Build AppDemo, verificamos que no existe ningún error y continuaremos creando nuestros otros dos formularios Base heredados de FormBaseBase.

 

  1. En el Solution Explorer, click derecho sobre la carpeta Base, click en Add, click en New Item … y se nos presentara una ventana con las plantillas incluidas Visual Studio, seleccione Inherited Form y le ponemos por Nombre FormBaseEscenario.vb, inmediatamente debemos de seleccionar de que formulario ha de heredar su funcionalidad, seleccionamos FormBaseBase, y presionamos OK.

 

Figura 4

 

  1. Seguidamente procedemos a asignarle el NameSpace a nuestro nuevo formulario, asignándole el NameSpace _3Dev.AppDemo.Base, recordar realizar la misma modificación para la clase parcial FormBaseEscenario.Designer.vb (Para poder observar este archivo debemos asegurarnos de que la opción Show All Files este habilitada – ver figura 4.1 - en el Solution Explorer). El código de la clase quedaría como se muestra en el siguiente código.

 

 

Figura 4.1

 

 

Namespace _3Dev.AppDemo.Base

 

    Public Class FormBaseEscenario

 

    End Class

 

End Namespace

 

  1. En el Solution Explorer, click derecho sobre la carpeta Base, click en Add, click en New Item … y se nos presentara una ventana con las plantillas incluidas Visual Studio, seleccione Inherited Form y le ponemos por Nombre FormBaseMantenimiento.vb, inmediatamente debemos de seleccionar de que formulario ha de heredar su funcionalidad, seleccionamos FormBaseBase, y presionamos OK; como en el caso anterior procedemos a asignarle el NameSpace _3Dev.AppDemo.Base (Nota: No olvidar el contemplar el punto 7).

 

 

Paso 4: Crear la interfaces del modelo de objetos de la capa de  

                Presentación.

 

  1. En el Solution Explorer, click derecho sobre AppDemo, click en Add, click en New Folder y tipeamos Interface.

 

  1. En el Solution Explorer, click derecho sobre la carpeta Interface, click en Add, click en Class … y tipeamos IFormBase.vb, reemplazamos el código generado y copiamos los siguiente y grabamos el proyecto.

 

Namespace _3Dev.AppCode.Interface

 

    Public Interface IFormBase

 

        Sub ConfigurarGrilla()

        Sub CargarGrilla()

        Sub Imprimir()

        Sub LlenarCombo()

 

    End Interface

 

End Namespace

 

  1. Nuevamente en el Solution Explorer, click derecho sobre la carpeta Interface, click en Add, click en Class … y tipeamos IFormMantenimiento.vb, reemplazamos el código generado y copiamos los siguiente y grabamos el proyecto.

 

 

Namespace _3Dev.AppCode.Interface

 

    Public Interface IFormMantenimiento

 

        Sub GrabarTab()

 

        Sub LlenarCombos()

 

        Function LlenarEntidad(ByVal Entidad As DataSet) As _

                 DataSet

 

    End Interface

 

End Namespace

 

 

 

  1. En el Solution Explorer, click derecho sobre AppDemo, click en Add, click en Class y tipeamos Enumerados. Y adicionamos el siguiente código esta clase nos ayudara temporalmente a definir los enumerados que necesitaremos mientras se crea el componente de Utilitario (HelperUtilitario)

 

 

Namespace _3Dev.AppDemo

 

    Public Class Enumerados

 

        Public Enum ModoFormulario

            N = 1

            M = 2

            C = 3

            D = 4

        End Enum

 

    End Class

 

End Namespace

 

 

Paso 5: Implementar los formularios Base de la Capa de Presentación

 

  1. Adicionemos funcionalidad a nuestro Formulario Base, este formulario (FormBaseEscenario.vb) nos servirá de ventana de selección de registros para su edición o eliminación, así como también para impresión o filtrado de la información. Agreguemos el siguiente código a FormBaseEscenario.

 

Imports _3Dev.AppCode.Interface

 

Namespace _3Dev.AppDemo.Base

 

    Public Class FormBaseEscenario

        Implements _3Dev. AppDemo.Interface.IFormBase

 

 

#Region " Implementación de la Interface IFormBase "

 

        Public Overridable Sub ConfigurarGrilla() _

            Implements [Interface].IFormBase.ConfigurarGrilla

 

        End Sub

 

        Public Overridable Sub Imprimir() _

            Implements [Interface].IFormBase.Imprimir

 

        End Sub

 

 

        Public Overridable Sub LlenarCombo() _

            Implements [Interface].IFormBase.LlenarCombo

 

        End Sub

 

        Public Overridable Sub CargarGrilla() _

            Implements [Interface].IFormBase.CargarGrilla

 

        End Sub

 

#End Region

 

#Region " Propiedades de la Clase "

 

        Private lcaption As String = String.Empty

        ''' <summary>

        ''' Permite definir un Etiqueta descriptiva del         

        ''' formulario

        ''' </summary>

        ''' <value></value>

        ''' <returns></returns>

        ''' <remarks></remarks>

        Public Property Caption() As String

            Get

                Return lcaption

            End Get

            Set(ByVal value As String)

                lcaption = value

            End Set

        End Property

 

#End Region

 

    End Class

 

End Namespace

 

  1. Ahora procedemos a abrir nuestro Formulario Base FormBaseMantenimiento.vb este formulario nos servirá de para dar mantenimiento o realizar algún proceso en la Carpeta ..\HOL\Archivos\ tenemos el archivo FormBaseMantenimiento.txt, reemplace el contenido de este archivo en el formulario Base FormBaseMantenimiento.vb

 

Paso 6: Construyendo el Diagrama de Clases.

 

  1. En el Solution Explorer, click derecho sobre AppDemo, click en Add, click en ClassDiagram, seleccionamos y tipeamos DiagramaUI.cd. Sobre este diseñador procederemos a arrastrar las carpetas Base e Interface, como se muestra en el siguiente gráfico.

 

Figura 5: Diagrama de Clases Final

 

  1. Pero el Diagrama de Clases nos brinda bastante funcionalidad al momento de diseñar como en la etapa de construcción de nuestros componentes; existen muchas características que podemos aprovechar para documentar o revisar las dependencias de nuestras clases pero una de las características mas interesante es la posibilidad de modificar el código desde aquí; si bien el código escrito y las modificaciones sobre este, pueden reflejarse en él; también podemos modificar el diagrama y ver los cambios en el código.

 

 

Figura 6: Menú de Diagrama Clases

 

En el ToolBar de Visual Studio habilitaremos la opción  Display Name and Type () y observaremos los tipos de datos definidos dentro de nuestra clase.

 

 

Figura 6: Clase FormBaseBase

 

 

  1. Ahora modificaremos el código desde el diagrama. En el Diseñador del Class Diagram, click en FormBaseMantenimiento, click derecho, click en Add, click en Property y escribimos DemoProperty.

 

Figura 7: Modificación de Código con el Diseñador de Clases

 

 

  1. Ahora hacemos click derecho sobre la propiedad creada DemoProperty, click en ViewCode, se mostrara una sección del código como esta con los valores creadas por defecto.

  

 

       Public Property DemoProperty() As Integer

            Get

 

            End Get

            Set(ByVal value As Integer)

 

            End Set

        End Property

 

 

  1. Modifiquemos con el siguiente código la propiedad DemoProperty, con los siguientes valores, y seguidamente grabamos el proyecto. Visualicemos Class Diagram ahora veamos la clase modificada observemos que los cambios realizados son actualizados directamente en el diagrama.

 

 

        Private lDemoProperty As Object

        Protected WriteOnly Property DemoProperty() As Object

            Set(ByVal value As Object)

                lDemoProperty = value

            End Set

        End Property

 

Figura 8: Clase Actualizada con el Diseñador de Clases

 

Así también podemos seguir probando la adición de Constructores, métodos, variables locales, estructuras, constantes, etc.

 

  1. Antes de cerrar el proyecto procedemos a eliminar la propiedad creada, grabamos el proyecto y cerramos el Visual Studio

 


 

Figura 9: Eliminación de la Propiedad de

Prueba DemoProperty

 

Joel Francia H. es Docente Universitario. Trabaja como Instructor, Consultor y Desarrollador de aplicaciones .net. Cuenta con las certificaciones MCAD, MCSD, MCT, y es además MVP en C# .net y expone regularmente en eventos técnicos y conferencias a nivel nacional. Su trabajo se centra actualmente en el desarrollo de aplicaciones distribuidas, implementaciones de Servicios Web, .Net Remoting, Windows Communcation Foundation y Modelos de Arquitectura de Software.

 

posted Tuesday, December 19, 2006 12:15 AM by jfrancia | 0 Comments
Attachment(s): image001.gif

PPT sobre MDA, Fabrica de Software y Frameworks de desarrollo

Este archivo contiene varias presentaciones sobre exposiciones relacionadas hechas por los alumnos.

http://www.yourfilelink.com/get.php?fid=86701

Joel

posted Saturday, April 22, 2006 11:25 AM by jfrancia | 1 Comments

More Posts Next page »
Powered by Community Server, by Telligent Systems