Posts recientes

El contenido de este blog tiene una licencia Creative Commons.
Creative Commons

Consejos para mejorar el rendimiento de tu Entity Framework (III)

Deshabitar el control de cambios.
Una instancia ObjectContext  crea un  objeto ObjectStateEntry que se encargará de seguir los cambios que se hacen en las entidades (las propiedades se marcan como modificadas y pero también se guardan los valores originales).
Este seguimiento provoca una carga, que es innecesaria si el objeto no se va a modificar o si se envian los datos a través de un webservice, y que puede reducirse usando la opción MergeOption.NoTracking.

Deshabitar la Concurrencia Optimista.
Linq to SQL admite el control de simultaneidad optimista (técnica que antes de relizar un cambio investiga si otras transacciones han cambiado los valores de una fila antes de que se envíen los cambios, y que bloquea el registro para evitar los conflictos de simultaneidad).
Sin embargo, si la aplicación no tiene problemas de concurrencia, o si puede ejecutarse en modo "la última actualización gana", entonces la carga generada por el UpdateCheck es innecesaria. Por eso se especifica UpdateCheck.Never para deshabilitar la concurrencia en Linq to SQL.
Autor: Isabel Cabezas
Publicado: 26/02/2010  9:21 | 0  Comentarios | 0  Enlaces a este post

Error de inicio de sesión recurrente al navegar una web local

A partir de las versiones de Microsoft Windows XP SP2, Microsoft Windows Server 2003 SP1 y en general en Microsoft Windows Server 2008 se da un curioso problema que nos puede llevar de cabeza un buen rato. Si tenemos un sitio web alojado en local, que responde bajo un FQDN o host header y lo intentamos navegar en local (no desde otra máquina), nos pasará que nos pedirá constantemente validación de credencial de usuario. Por mucho que proporcionemos unas credenciales válidas nos devolverá constantemente errores HTTP 401.1.

Este efecto es debido a nuevas medidas de seguridad en la plataforma y que se pueden solucionar tocando una clave del registro. La forma más sencilla de evitar este efecto es anulando esta nueva característica. Para ello y según instrucciones de Microsoft:

  1. Haga clic en Inicio y en Ejecutar, escriba regedit y haga clic en Aceptar.
  2. En el Editor del Registro, busque la clave siguiente y después haga clic en ella:

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa

  3. Haga clic con el botón secundario del mouse (ratón) en Lsa, seleccione Nuevo y, a continuación, haga clic en Valor DWORD.
  4. Escriba DisableLoopbackCheck y, a continuación, presione Entrar.
  5. Haga clic con el botón secundario del mouse en DisableLoopbackCheck y, a continuación, haga clic en Modificar.
  6. En el cuadro Información del valor, escriba 1 y haga clic en Aceptar.
  7. Cierre el Editor del Registro y reinicie el equipo.

Os recomiendo visitar http://support.microsoft.com/kb/896861

Autor: Rubén Claramunt Vicente
Publicado: 24/02/2010  12:59 | 0  Comentarios | 0  Enlaces a este post

Perdida del Focus en UpdatePanel

Todos nos habremos encontrado que cuando hacemos un PostBack con los UpdatePanel de Microsoft, nos encontramos que se nos deslocaliza el focus.

Esto nos provoca que tengamos que estar colocando el foco en el siguiente control, ¿pero qué pasa cuándo el foco, no lo tiene el siguiente tabindex?

Para solucionarlo, solo hay que colocar el siguiente JScript en nuestro código, para que te guarde el control que tenía el foco antes del postback. Para ello deberemos colocarlo dentro del ScriptManager como se muestra a final de esta entrada
var lastFocusedControlId = "";
function focusHandler(e) { 
document.activeElement = e.originalTarget;
} 
function appInit() { 
if (typeof (window.addEventListener) !== "undefined") {
window.addEventListener("focus", focusHandler, true); 
}
Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(pageLoadingHandler); 

Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoadedHandler); 
} 
function pageLoadingHandler(sender, args) {
 lastFocusedControlId = typeof (document.activeElement) === "undefined" ? "" : document.activeElement.id; 
} 
function focusControl(targetControl) { if (Sys.Browser.agent === Sys.Browser.InternetExplorer) 
{ var focusTarget = targetControl;
 if (focusTarget && (typeof (focusTarget.contentEditable) !== "undefined")) { oldContentEditableSetting = focusTarget.contentEditable;
 focusTarget.contentEditable = false;
 } 
else { 
focusTarget = null; 
} 
targetControl.focus(); 
if (focusTarget) { 
focusTarget.contentEditable = oldContentEditableSetting;
 } 
} 
else { 
targetControl.focus();
 } 
} 
function pageLoadedHandler(sender, args) { 
if (typeof (lastFocusedControlId) !== "undefined" && lastFocusedControlId != "") { 
var newFocused = $get(lastFocusedControlId); 
if (newFocused) { 
focusControl(newFocused); 
} 
} 
} 
Sys.Application.add_init(appInit);
 

<asp:ScriptManager runat="server" ID="ScriptManager1" >
<Scripts>
<asp:ScriptReference Path="~/Script/UpdatePanelFocus.js" />
</Scripts>
</asp:ScriptManager>

Autor: Javier Tirado Pampín
Publicado: 22/02/2010  12:47 | 1  Comentario | 0  Enlaces a este post

Abrir documentos Office 2010 desde un sitio SharePoint

Desde que estoy trabajando con la versión Beta de Microsoft Office 2010 he tenido problemas para abrir los documentos de Office de mi sitio SharePoint. Cada vez que quería  abrir un documento de Office, me aparecía un mensaje indicándome que era imposible abrir el documento, obligándome a descargarlos en local antes de poder trabajar con ellos.  Hoy en encontrado la solución y os hago un resumen para resolver el problema rápidamente.
    1. Abrir Internet Explorer
    2. Seleccionar [Herramientas] -> [Opciones de Internet]
    3. Seleccionar la pestaña [Conexiones]
    4. Hacer click en [Configuración de LAN]
    5. Marcar el check "Usar un servidor proxy para LAN"
    6. Informar la "Dirección" con el valor 127.0.0.1
    7. Hacer click en [Opciones avanzadas]
    8. En "Excepciones" teclear: *.*
    9. Pulsar [Aceptar], [Aceptar] y otra vez [Aceptar].

Y tema resuelto.

Vía: http://www.benstegink.com/2009/08/28/office-2010-and-sharepoint-2007/

Autor: Emilio Martín
Publicado: 18/02/2010  12:08 | 2  Comentarios | 0  Enlaces a este post

Regenerar los SIDs de usuarios tras una migración de SharePoint

No son pocas las ocasiones en que hemos tenido problemas con los usuarios tras una migración de un entorno desarrollado en SharePoint. Desplegamos el nuevo entorno, todo funciona genial, entramos con cuentas de administrador y todo bien, pero los usuarios de a pie no pueden acceder.
Esto es debido en muchas ocasiones a que el entorno de Active Directory es una réplica y aunque se conserven los nombres de usuario (loginname) no se conservan los SIDs internos. Una solución sencilla y rápida consiste simplemente sustituir los SIDs que almacena SharePoint en base de datos por los nuevos SIDs de Active Directory. Con ello se restablecerán los accesos a través de las nuevas cuentas. Una forma de conseguirlo es accediendo directamente a base de datos y a nuestro propio riesgo (realizar copias de seguridad y demás).
Aquí tenéis un script de base de datos que ataca la tabla UserInfo y que permite restablecer estos identificadores. Muchas suerte!
DECLARE @login varchar(40), @systemid varbinary(128)

DECLARE curUsers CURSOR LOCAL FOR
SELECT tp_login, tp_systemid FROM userinfo where tp_deleted = 0

OPEN curUsers

	FETCH NEXT FROM curUsers INTO @login, @systemid

WHILE @@FETCH_STATUS = 0
BEGIN
	PRINT 'Resetting user ' + @login + ' to new SID '
	PRINT suser_sid(@login)
	UPDATE UserInfo
		SET tp_systemid = suser_sid(tp_login) WHERE CURRENT OF curUsers
	FETCH NEXT FROM curUsers INTO @login, @systemid
END

CLOSE curUsers
DEALLOCATE curUsers

GO
Autor: Rubén Claramunt Vicente
Publicado: 17/02/2010  10:56 | 0  Comentarios | 0  Enlaces a este post

Dibujar los ficheros adjuntos en una DataFormWebPart

Haciendo uso de SharePoint Designer y de la versatil DataFormWebPart podemos conectar contra múltiples origenes de datos, entre ellos listas de SharePoint, y renderizar su contenido en formato HTML a través de un XSLT.
El XML devuelto por el SPDataSource nos ofrece las propiedades de la lista, entre ellas una propiedad, @Attachments, que nos devuele un booleano indicando si el elemento de lista tiene o no ficheros adjuntos. Pero, ¿qué pasa si lo que queremos es obtener los ficheros adjuntos?
Con el diseñador de SharePoint Designer no es posible ya que no obtenemos esa información, pero si que podemos recurrir a un sencillo control de servidor de SharePoint para dibujar los enlaces a los ficheros adjuntos. Tan solo debemos incluir el siguiente código dentro del XSL de la DataFormWebPart.
<xsl:element name="SharePoint:AttachmentsField">
<xsl:attribute name="runat">server</xsl:attribute>
<xsl:attribute name="FieldName">Attachments</xsl:attribute>
<xsl:attribute name="ControlMode">Display</xsl:attribute>
<xsl:attribute name="Visible">true</xsl:attribute>
<xsl:attribute name="ItemId"><xsl:value-of select="@ID" /></xsl:attribute>
</xsl:element>								
Autor: Rubén Claramunt Vicente
Publicado: 15/02/2010  9:34 | 0  Comentarios | 0  Enlaces a este post

FileUpload, GridView y UpdatePanel

Si alguna vez han utilizado un control FileUpload de .NET dentro de un UpdatePanel se habrán encontrado con que no son controles compatibles, es decir, cuando se ejecuta el evento del botón que sube el fichero te encuentras con que el PostedFile del control FileUpload es nulo.
Caso base:
<asp:UpdatePanel ID="uPnl" runat="server">
  <ContentTemplate>
    <asp:FileUpload ID="flUpl" runat="server"></asp:FileUpload>
    <asp:Button ID="btnSubir" runat="server" Text="Subir" OnClick="btnSubir_Click"></asp:Button>
  </ContentTemplate>
</asp:UpdatePanel>
Si se busca por la red se encuentran varias soluciones, la más sencilla es agregar a la lista de triggers del UpdatePanel un nuevo PostBackTrigger con el ControlId apuntando al botón de subir fichero de nuestro FileUpload (en el ejemplo anterior 'btnSubir').
<asp:UpdatePanel ID="uPnl" runat="server">
  <ContentTemplate>
    <asp:FileUpload ID="flUpl" runat="server"></asp:FileUpload>
    <asp:Button ID="btnSubir" runat="server" Text="Subir" OnClick="btnSubir_Click"></asp:Button>
  </ContentTemplate>
  <Triggers>
    <asp:PostBackTrigger ControlID="btnSubir" />
  </Triggers>
</asp:UpdatePanel>
Ahora bien, me encontré con el particular caso que el FileUpload se encontraba en el header de un GridView, y éste, a la vez, dentro del UpdatePanel, de la siguiente forma:
<asp:UpdatePanel ID="uPnl" runat="server">
  <ContentTemplate>
    <asp:GridView ID="gvw" runat="server">
      <Columns>
        <asp:TemplateField>
          <asp:HeaderTemplate>
            <asp:FileUpload ID="flUpl" runat="server"></asp:FileUpload>
            <asp:Button ID="btnSubir" runat="server" Text="Subir" OnClick="btnSubir_Click"></asp:Button>
          <asp:/HeaderTemplate>
        </asp:TemplateField>
      </Columns>
    </asp:GridView>
  </ContentTemplate>
  <Triggers>
    <asp:PostBackTrigger ControlID="btnSubir" />
  </Triggers>
</asp:UpdatePanel>
Al estar el control FileUpload dentro del GridView, sale el siguiente error:
A control with ID 'btnSubir' could not be found for the trigger in UpdatePanel 'uPnl'.
Esto sucede porqué se cambian los ID's dinámicamente cuando se ejecuta la página y por lo tanto el botón con ID 'btnSubir' no se llama igual.
Una vez en este punto, prové a eliminar el trigger en el UpdatePanel de la página aspx y a ponerlo dinámicamente (para poder coger el ClientID, que contiene el identificador real del control) en el evento gvw_RowDataBound de la siguiente forma:
if (e.Row.RowType == DataControlRowType.Header)
{
	PostBackTrigger pt = new PostBackTrigger();
	pt.ControlID = e.Row.Cells[0].FindControl("btnSubir").ClientID;
	uPnl.Triggers.Add(pt);
}
Igualmente, siguió saliendo el mismo error que al principio, cuando quería subir el fichero mediante el botón de añadir el FileUpload no tenía ningún fichero introducido.
Finalmente hallé la solución implementando el evento PreRender del botón que sube el fichero (en el ejemplo 'btnSubir') y utilizar el ScriptManager:
protected void btnSubir_PreRender(object sender, EventArgs e)
{
	Button btn = (Button)sender;
	ScriptManager newScriptManager = (ScriptManager)Page.FindControl("ScriptManager1");
	newScriptManager.RegisterPostBackControl(btn);
}
Una vez implementado, cualquier botón dentro del GridView actualiza tan sólo el GridView, a excepción del botón de subida del fichero (btnSubir) del Header que hace un PostBack (necesario para que funcione el FileUpload).
Autor: Anna Vilalta Gili
Publicado: 12/02/2010  15:02 | 2  Comentarios | 0  Enlaces a este post

Matrix, agrupaciones y totales.

1.- Introducción
Una matriz se usa habitualmente como herramienta para mostrar datos agrupados e información de resumen.
Nos permite agrupar datos por varios campos o expresiones en grupos de filas y de columnas. Así mismo las matrices nos ofrecen una funcionalidad similar a la de las tablas de referencias cruzadas y las tablas dinámicas.
La información que nos muestran las celdas de la matriz, es en sí, una serie de valores agregados cuyo ámbito es la intersección de los grupos de filas y de columnas a los que pertenece la celda.
Además la matriz nos permite dar formato a las filas y columnas para poder enfatizar y resaltar los datos que creamos más importantes dentro de la misma.
 
2.-Agregando una matriz al informe
Para agregar una matriz al informe, lo único que debe hacer es arrastrar el elemento matriz desde la barra de herramientas hasta la superficie de diseño.
El aspecto inicial de la matriz será:
Matriz en blanco con 1 fila y 1 grupo de columnas
Como se puede ver tiene un grupo de filas, uno de columnas y una celda de datos.
Si seleccionamos la matriz, aparecerán los identificadores de fila y columna como se ve en la siguiente figura:
Nueva matriz agregada desde el cuadro de herramientas, seleccionada
Lo siguiente que debe hacer es agregar grupos arrastrando campos de conjunto de datos hasta las áreas Grupos de filas y Grupos de columnas del panel.
Grupo de columnas Geography y fila Categoría, Matriz
La matriz inicialmente es una plantilla basada en la región de datos tabla(Tablix). La diferencia reside en que puede continuar desarrollando el diseño de la matriz agregando grupos de filas o de columnas anidados o adyacentes, o incluso filas de detalles.
 
3.-Agregando grupos primarios o secundarios
Para agregar grupos de datos tanto primarios como secundarios lo único que debe hacer es arrastrar un campo del conjunto de datos desde el panel de datos del informe hasta el área Grupos de filas o Grupos de columnas del panel Agrupación. Según coloque el campo en la jerarquía de grupos se definirá como primario o secundario, si lo coloca por encima de un grupo existente se definirá como primario y debajo se convertirá en secundario, se pueden modificar los niveles de primarios y secundarios en cualquier momento modificando su posición en el Grupo al que pertenecen(filas o columnas) esta acción se puede realizar desde las propiedades de la matriz en la sección de grupos, además puede personalizar cada uno de los grupos desde el cuadro de diálogo Grupo de Matrix permitiéndonos modificar su nombre y expresiones(modificar, añadir) entre otras características.
Grupos de columnas y filas anidadas de matriz con totales
4.-¿Cómo añadir/eliminar grupos de totales?
Estas operaciones tienen un acceso y funcionalidad realmente trivial una vez se conoce como realizarlas, en este caso será tan fácil como pulsar el botón derecho del ratón sobre el campo agupado (fila o columna) y activar/desactivar la acción agregar total ().
Al utilizar esta funcionalidad se realiza un "total" predeterminado por reporting, en caso de querer realizar un "total" más concreto y no genérico se puede hacer modificando la expresión existente.
Autor: David Acosta Lesmes
Publicado: 09/02/2010  10:25 | 0  Comentarios | 0  Enlaces a este post

Consejos para mejorar el rendimiento de tu Entity Framework (II)

Pre-generar las vistas.
Para que una consulta se pueda ejecutar con un Entity Data Model (EDM), el Entity Framework (EF) genera un conjunto de vistas que se utilizan para tener acceso a la base de datos.
El EF genera vistas las primera vez que se ejecuta una consulta, y se mantiene durante toda la vida de  la instancia del ObjectContext, pero este proceso es el más costoso de toda la consulta, ya que tarda aproximadamente un 50% de la operación total.  Por eso, EF premite generar previamente estas vistas e incluirlas en el proyecto compilado, aunque esto también tiene una desventaja, y es que implica que hay que tener las vistas sincronizadas con los cambios del modelo de datos.
Las vistas pre-generadas se validan en tiempo de ejecución para asegurarse de que son coherentes con la versión actual de EDM, pero se puede omitir si el proceso de generación está generando los archivos de asignación y modelo en el directorio de salida (en el Explorador de Modelos, en la ventana propiedades, cambiar la opción "Procesamiento de artefactos de metadatos" a "Copiar en el directorio de resultados" y recompilar).
Para pre-generarlas se usa una herramienta llamada "Generador de EDM", que suele estar en Windows\Microsoft.NET\Framework\v3.5 y se llama EdmGen.exe si no lo encuentras Microsoft facilita su descarga desde aquí).
Para generar las vistas y agregarlas a un proyecto C# se usa esta  herramienta de línea de comandos con un el parámetro de generación de vistas (/mode:ViewGeneration).
"%windir%\Microsoft.NET\Framework\v3.5\EdmGen.exe" 
    /mode:ViewGeneration 
    /language:CSharp 
    /nologo 
    "/inssdl:MyEntityModel.ssdl" 
    "/incsdl:MyEntityModel.csdl" 
    "/inmsl:MyEntityModel.msl" 
    "/outviews:MyEntityModel.Views.cs"
También se puede hacer desde la Consola de comandos del VS2008 (Inicio -> todos los programas -> MSVS2008 -> VS Tools -> VS2008 Command Prompt).
O bien:
1. En el Explorador de soluciones, seleccione el proyecto para el que desea especificar el evento de generación.
2. En el menú Proyecto, haga clic en Propiedades.
3. Seleccione la ficha Generar eventos.
4. la ventana Línea de comandos del evento anterior a la compilación, agregue el "evento anterior a la generación" añadir el comando anterior (en azul) sin saltos de línea.
5. Genere la solución.
Para volver a agregar los archivos de asignación y modelo como recursos incrustados para los proyectos ASP.NET, modifique el parámetro Metadata del atributo connectionString (puede encontrar más información sobre cómo hacer esto en esta entrada anterior de este blog)
 
 
Autor: Isabel Cabezas
Publicado: 04/02/2010  18:31 | 0  Comentarios | 0  Enlaces a este post