Principales respuestas
Llamar método dentro de otro método

Pregunta
-
Buenas tardes,
Estoy creando un WebService con C# el cual contiene un método llamado PAGO, dentro de éste, ejecuto otro método booleano llamado Autenticar para validar un usuario y una contraseña, de esta forma:
public class ServicioMarquez : System.Web.Services.WebService { SqlConnection cnn; SqlCommand cmd; string mensaje; [WebMethod] public MetodoPago PAGO(string usu_ws, string pass_ws) { MetodoPago propiedades = new MetodoPago(); if (Autentica(usu_ws, pass_ws) == true) { propiedades.cod_error = "1"; propiedades.des_error = "AUTENTICACIÓN CORRECTA"; } else { propiedades.cod_error = "2"; propiedades.des_error = mensaje; } return propiedades; } private bool Autentica(string usu, string pass) { bool finalizado = true; string password = ""; try { using (cnn = new SqlConnection(ConfigurationManager.ConnectionStrings["BD_DESARROLLOConnetionString"].ToString())) { cnn.Open(); string query = "SELECT USU,PASS FROM USUARIO WHERE USU=@USU"; cmd = new SqlCommand(query, cnn); cmd.Parameters.AddWithValue("@USU", usu); SqlDataReader reader = cmd.ExecuteReader(); if (reader.Read()) { password = Convert.ToString(reader["PASS"]); } cnn.Close(); if (password == "" | password != pass) { finalizado = false; } } } catch (Exception ex) { finalizado = false; mensaje = Convert.ToString(ex.Message); } return finalizado; } }
Mi pregunta es: ¿Es correcto invocar un método dentro de otro? es válido la forma en que lo estoy realizando o hay otra mejor práctica para realizarlo?
Carlos Márquez
- Editado Carlos Márquez lunes, 27 de enero de 2014 11:59
Respuestas
-
mas pasa por la cuestión del ámbito y que la funcionalidad está amarrada a la variable mensaje que es una variable global,
exacto, la idea es definir las cosas con la menor ambito que sea necesario
no pasa por u tema de poder o no poder, sino por un tema de como diseñas de forma reutilizable y mantenible, lo global siempre es sinonimo de problemas, a veces es necesario la cuestion es que no sea todo global
si vas a definir una funcionalidad que valida digamos temperatudas, no definas los alores de las temperaturas en una variable global y que el metodo lo tome de alli
sino que la funciona reciba estos valores en concreto que debe usar, de esa forma si mas adelante alguine requiere de la misma funcionalidad puede llevarsela y reusarla si tener que estar revisando todo el codigo para ver donde sale cada variable
saludos
Leandro Tuttini
Blog
Buenos Aires
Argentina- Marcado como respuesta Carlos Márquez martes, 28 de enero de 2014 14:16
Todas las respuestas
-
Hola Carlos,
Invocar un método dentro de otro es correcto, lo que no es correcto es cómo autentificas al usuario. Para ello los WebService tienen muchos mecanismos. Tienes lo básico aquí: http://msdn.microsoft.com/library/system.web.security(v=vs.110).aspx y aquí: http://msdn.microsoft.com/library/vstudio/system.web.services.webservice.user(v=vs.100).aspx
Y aquí tienes un artículo sobre seguridad en web services: http://msdn.microsoft.com/en-us/library/ff648318.aspx
Y lo primero de todo: no guardes nunca un password en texto plano en la bbdd, haz un hash+salt como mínimo, o encripta, tienes un montón de librerías en el framework para cifrar datos.
Un saludo,
Juanma
- Propuesto como respuesta Sergio ParraModerator domingo, 26 de enero de 2014 23:28
-
Hola, Juanma.
Lo de la parte de la autenticación fue algo rápido que hice para tratar de ilustrar el ejemplo, siempre suelo realizar esa parte con una clase y mi propio método de encriptación, lo que quería asegurarme era si la parte del llamado del método dentro de otro era la correcta, de todas formas voy a revisar los mecanismos para autenticar que me envías.
Carlos Márquez
-
hola
algo que no se si has evaluado es el transporte de los datos que envias al invocar el web service
o sea vas a usar este servicio en una red interna, o por internet, porque algo que aconsejaria es que evalues usar SSL para asegurar la invocacion por un medio seguro
ya que si envias el usuario y password directo cualquiera que este escuchando la red podrias interceptar el mensaje soap
---
lo que tambien veo mal es como asignas la variable mensaje, alli rompes con cualquier idea de encapsular funcionalidad
si vas a enviar un mensaje porque no usas el Exception, osino haz que la clase MetodoPago la cree y directamente el metodo Autenticar()
eso de definir una variable publica "mensaje" no es correcto
saludos
Leandro Tuttini
Blog
Buenos Aires
Argentina -
Hola, Tuttini.
si vas a enviar un mensaje porque no usas el Exception, osino haz que la clase MetodoPago la cree y directamente el metodo Autenticar()
Puedo hacer una segunda instancia de mi clase MetodoPago dentro del método Auntentica y en el catch asignar la propiedad des_error el mensaje de error? de esta forma...
private bool Autentica(string usu, string pass) { MetodoPago propiedades = new MetodoPago(); bool finalizado = true; string password = ""; try { using (cnn = new SqlConnection(ConfigurationManager.ConnectionStrings["BD_DESARROLLOConnetionString"].ToString())) { //CODIGO } catch (Exception ex) { finalizado = false; propiedades.des_error=convert.tostring(ex.message); } return finalizado; }
Carlos Márquez
-
Puedo hacer una segunda instancia de mi clase MetodoPago dentro del método Auntentica y en el catch asignar la propiedad des_error el mensaje de error?
no eso no funciona porque es otra instancia que defines de forma local, si asignaras el valor pero no lo recibiras en el webmethod para poder devolverlo como resultado
private MetodoPago Autentica(string usu, string pass) { string password = ""; try { using (cnn = new SqlConnection(ConfigurationManager.ConnectionStrings["BD_DESARROLLOConnetionString"].ToString())) { //CODIGO } return new MetodoPago() { cod_error = "1", des_error = "AUTENTICACIÓN CORRECTA" }; } catch (Exception ex) { return new MetodoPago() { cod_error = "2", des_error = ex.Message }; } }
la validacion que genere directamente la respuesta, asi no necesitas tener nada global para pasar datos
saludos
Leandro Tuttini
Blog
Buenos Aires
Argentina -
Hola, Tuttini.
Entonces usar variables de esta manera es incorrecto?
public partial class Form1 : Form { string variable; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { variable = "Hola Mundo"; MessageBox.Show(variable); }
Carlos Márquez
-
Hola, Tuttini.
Y que tal usando variables privadas? de esta forma si es permitido y no rompe el encapsulamiento?
public partial class Form1 : Form { private string variable; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { variable = "hola"; MessageBox.Show(variable); } }
Carlos Márquez
-
Hola, Tuttini.
Usando variables privadas es valido hacer esto, no? declarando la variable mensaje como privada
public class ServicioMarquez : System.Web.Services.WebService { SqlConnection cnn; SqlCommand cmd; private string mensaje; //Declarando mensaje como privada [WebMethod] public MetodoPago PAGO(string usu_ws, string pass_ws) { MetodoPago propiedades = new MetodoPago(); if (Autentica(usu_ws, pass_ws) == true) { propiedades.cod_error = "1"; propiedades.des_error = "AUTENTICACIÓN CORRECTA"; } else { propiedades.cod_error = "2"; propiedades.des_error = mensaje; } return propiedades; } private bool Autentica(string usu, string pass) { bool finalizado = true; string password = ""; try { using (cnn = new SqlConnection(ConfigurationManager.ConnectionStrings["BD_DESARROLLOConnetionString"].ToString())) { cnn.Open(); string query = "SELECT USU,PASS FROM USUARIO WHERE USU=@USU"; cmd = new SqlCommand(query, cnn); cmd.Parameters.AddWithValue("@USU", usu); SqlDataReader reader = cmd.ExecuteReader(); if (reader.Read()) { password = Convert.ToString(reader["PASS"]); } cnn.Close(); if (password == "" | password != pass) { finalizado = false; } } } catch (Exception ex) { finalizado = false; mensaje = Convert.ToString(ex.Message); } return finalizado; } }
Carlos Márquez
-
-
si eso lo se, pero que pasa si alguien se quiere llevar la funcionalida de autenticar par aimplementarla en otra funcionalidad?
digo sin declarar variables por fuera de de este no podrias llevartelo, ahi es donde apunto, autenticar es una funcionalidad que deberia tener una responsabilidad simple, no necesita algo global para informar de algun problema
podrias hacer que esta directamnte devuelva la clase con la descripcion del error, o podrias ahcer que devuelva un Exception lanzado por ti y sea captura por tu otra funcionalidad
quizas algo como esto
[WebMethod] public MetodoPago PAGO(string usu_ws, string pass_ws) { MetodoPago propiedades = new MetodoPago(); try { if (Autentica(usu_ws, pass_ws)) { propiedades.cod_error = "0"; propiedades.des_error = "AUTENTICACIÓN CORRECTA"; } else { propiedades.cod_error = "1"; propiedades.des_error = "NO AUTENTICA"; } } catch(Exception ex) { propiedades.cod_error = "2"; propiedades.des_error = ex.Message; } return propiedades; } private bool Autentica(string usu, string pass) { using (SqlConnection cnn = new SqlConnection(ConfigurationManager.ConnectionStrings["BD_DESARROLLOConnetionString"].ToString())) { cnn.Open(); string query = "SELECT COUNT(*) FROM USUARIO WHERE USU=@USU AND PASS = @pass"; SqlCommand cmd = new SqlCommand(query, cnn); cmd.Parameters.AddWithValue("@USU", usu); cmd.Parameters.AddWithValue("@pass", pass); SqlDataReader reader = cmd.ExecuteReader(); int result = Convert.ToInt32(cmd.ExecuteScalar()); return result != 0 } }
no definas el connection y command de forma global, se puede definir localmente en el metodo
saludos
Leandro Tuttini
Blog
Buenos Aires
Argentina -
Hola, Tuttini.
Vos decís: Pero que pasa si alguien se quiere llevar la funcionalida de autenticar par aimplementarla en otra funcionalidad?
digo sin declarar variables por fuera de de este no podrias llevartelo, ahi es donde apunto, autenticar es una funcionalidad que deberia tener una responsabilidad simple, no necesita algo global para informar de algun problema
Si te fíjas el método autenticar es privado y de tal forma no se va a poder autoimplementar desde otra parte, tenes razón en que quizás no necesite otra variable para informar de algún problema, es cierto, pero todavía no se porque debería de caer en un error de encapsulamiento, si es cierto mensaje es una variable global pero solo para esta clase ya que se sigue manteniendo como privada y no es accesible desde otra clase,
Me podes explicar por qué al usar la variable mensaje cae en error de encapsulación?
Carlos Márquez
-
Hola, Tuttini.
Para cerrar esta pregunta, entonces lo que vos queres decir es que no es una cuestión de variable publica porque la variable es privada, mas pasa por la cuestión del ámbito y que la funcionalidad está amarrada a la variable mensaje que es una variable global, entonces si alguien quisiera hacer uso de ella tendría que declarar siempre esa variable donde vaya a utilizar esa funcionalidad o en su defecto crear una variable como propiedad, todo esto pudiéndose evitar de la forma como propusiste. No pasa por ser una cuestión que No se pueda usar variables globales porque Si se puede, claro siempre recordando que se debe de usar el ámbito mas pequeño.
Te entendí bien?
Carlos Márquez
-
mas pasa por la cuestión del ámbito y que la funcionalidad está amarrada a la variable mensaje que es una variable global,
exacto, la idea es definir las cosas con la menor ambito que sea necesario
no pasa por u tema de poder o no poder, sino por un tema de como diseñas de forma reutilizable y mantenible, lo global siempre es sinonimo de problemas, a veces es necesario la cuestion es que no sea todo global
si vas a definir una funcionalidad que valida digamos temperatudas, no definas los alores de las temperaturas en una variable global y que el metodo lo tome de alli
sino que la funciona reciba estos valores en concreto que debe usar, de esa forma si mas adelante alguine requiere de la misma funcionalidad puede llevarsela y reusarla si tener que estar revisando todo el codigo para ver donde sale cada variable
saludos
Leandro Tuttini
Blog
Buenos Aires
Argentina- Marcado como respuesta Carlos Márquez martes, 28 de enero de 2014 14:16