Categories
.NET

Código fuente externo y Visual Studio .NET

Ohad Israeli comenta un problema de seguridad reportado en enero de este año. Este problema existe cuando Visual Studio ejecuta el código que está dentro del evento Load de un control de usuario o formulario, que a su vez forma parte de algún otro contenedor (también ocurre cuando se heredan controles/formularios)

Si bien es cierto que antes ya había experimentado este comportamiento -como seguramente varios de ustedes-, no lo había visto desde este punto de vista. Tendré que tener un poco más de cuidado para la próxima!

Categories
.NET

FillSchema y tablas temporales.

Hoy, mientras hacía pruebas en una aplicación desarrollada en C#, una rutina que se encargaba de obtener el esquema de procedimientos almacenados (Sql Server), mandaba errores -con el mensaje "Invalid object name '#temp...'"- por el hecho de que algunos de éstos hacían uso de tablas temporales.

El código en cuestión hacía algo como esto:

csharp:

DataTable tabla = new DataTable();

using (SqlDataAdapter da = new SqlDataAdapter("sp_test", "CadenaConexion"))
{
        da.SelectCommand.CommandType = CommandType.StoredProcedure;
        da.FillSchema(tabla, SchemaType.Source);
}

Y el procedimiento tenía una estructura parecida a:

sql:

CREATE procedure sp_test
AS

SELECT  a, b
INT0    #temp
FR0M    tabla1

SELECT  T.*, T2.c
FR0M    #temp T join tabla2 T2
0N      T.a = T2.a

go

Después de hacer una búsqueda y encontrar un par de páginas que aclararon mis dudas, finalmente tuve que modificar algunos procedimientos para que hagan uso de variables tipo table.

Nota: La sintáxis del procedimiento tiene errores intencionales debido a los problemas de configuración en el servidor donde se hospeda esta página

Categories
.NET AJAX ASP.NET

Script#

Script#, al igual que Google Web Toolkit, permite generar código javascript, utilizando en este caso cualquier lenguaje compatible con el .NET Framework.

csharp:

// Demo.cs
using System;
using ScriptFX;
using ScriptFX.UI;

namespace HelloWorld {

    public class Demo : IScriptlet {

        private Button _okButton;
        private XMLHttpRequest _request;

        public void Start() {

            _okButton = new Button(Document.GetElementById("okButton"));
            _okButton.Click += new EventHandler(this.OnOKButtonClick);
        }

        private void OnOKButtonClick(object sender, EventArgs e) {
            Callback completedCallback = new Callback(this.OnRequestComplete);

            _request = new XMLHttpRequest();
            _request.Onreadystatechange = Delegate.Unwrap(completedCallback);
            _request.Open("GET", "Hello.ashx", true);
            _request.Send(null);
        }

        private void OnRequestComplete() {
            if (_request.ReadyState == 4) {
                _request.Onreadystatechange = Function.Empty;
               
                Window.Alert(_request.ResponseText);
            }
        }
    }
}
 

En la página de demostración, lo único que se tiene que hacer es registrar la clase "HelloWorld.Demo".

html:

<!-- Demo.aspx -->
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
  <title>Demo Script#</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
      <input type="button" id="okButton"
        value="OK" />

    </div>
   
    <nStuff:Scriptlet runat="server"
      ScriptAssembly="HelloWorld"
      ScriptletType="HelloWorld.Demo" />

    </form>
</body>
</html>
csharp:

<%@ WebHandler Language="C#" Class="HelloHandler" %>

// Handler.ashx: Se encarga de procesar la petición.

using System;
using System.Web;

public class HelloHandler : IHttpHandler {

    public bool IsReusable {
        get {
            return true;
        }
    }

    public void ProcessRequest(HttpContext context) {
        HttpRequest request = context.Request;
        HttpResponse response = context.Response;

        string greeting = String.Empty;
        string name = request["name"];
        if (!String.IsNullOrEmpty(name))
        {
            greeting = "Hello " + HttpUtility.HtmlEncode(name) + "!";
        }
        else
            greeting = "Hello from server";

        greeting += " - Server time: " + DateTime.Now.ToShortTimeString();
     
        response.ContentType = "text/plain";
        response.Write(greeting);
    }
}

xml:

<!-- Web.config -->
<?xml version="1.0"?>
<configuration>

  <system.web>
    <pages>
      <controls>
        <add tagPrefix="nStuff" assembly="nStuff.ScriptSharp.Web" namespace="nStuff.ScriptSharp" />
      </controls>
    </pages>
  </system.web>

</configuration>

Pueden descargar el compilador de Script# desde http://www.nikhilk.net/Content/Samples/ScriptSharp.zip o ver un video demostrativo en http://www.nikhilk.net/Content/Video/ScriptSharpIntro.wmv

Categories
.NET Varios

Visual Studio 2005 & Ruby

Steel es un add-in para Visual Studio 2005 que permite utilizar Ruby en este IDE. Actualmente este add-in no tiene muchas cosas, pero está previsto que para futuras versiones éste tenga: un debugger, verificación de sintáxis al estilo de los "lenguajes estáticos" como C#, soporte para Intellisense, soporte para el desarrollo de aplicaciones basadas en Rails.

Pueden descargar los instaladores de este add-in desde http://www.sapphiresteel.com/static/pages/software/download.html

Categories
.NET

Instancia única de Formularios

Generalmente al trabajar con aplicaciones que tengan formularios MDI, se requiere que sólo exista una instancia de un formulario a la vez, si bien es cierto que ésto se puede lograr usando el patrón Singleton, esta forma de hacerlo se dificulta al tener una cantidad considerable de formularios hijos.

A continuación se muestra un método genérico para tener sólo una instancia por formulario:

csharp:

public Hashtable instancias = new Hashtable();

public Form AbrirVentana(Type tipo)
{
        return AbrirVentana(tipo.FullName);
}

public Form AbrirVentana(string tipo)
{
        try
        {
                Form formulario = instancias[tipo] as Form; // Recuperar la instancia, si existe
                if (formulario == null || formulario.IsDisposed)
                {
                        // Usar Reflection para crear una instancia
                        formulario = (Form)Activator.CreateInstance(null, tipo).Unwrap();
                        instancias[tipo] = formulario;
                }
                if (this.IsMdiContainer)
                        formulario.MdiParent = this;

                formulario.Activate();
                formulario.WindowState = FormWindowState.Normal;
                formulario.Show();
                return formulario;
        }
        catch (Exception ex)
        {
                // Procesar el error
                throw ex; // return null;
        }
}

Al código mostrado arriba falta hacerle unas cuantas modificaciones para darle un poco más de flexibilidad (puesto que sólo se basa en el tipo), pero para empezar creo que está bien.

Archivos Relacionados