Social Icons

Mostrando entradas con la etiqueta WSS. Mostrar todas las entradas
Mostrando entradas con la etiqueta WSS. Mostrar todas las entradas

jueves, 5 de abril de 2012

Esconder Editar en hoja de datos en el menu Acciones con código javascript

¿Volver después de todo este tiempo para escribir un post tan feo? Ese es exactamente mi estilo…
El título del post explica bastante bien cual era el objetivo a cumplir y todo el mundo sabe que esta no es la mejor forma, pero editar los permisos estaba dándonos problemas en otro lado así que decidimos hacerlo asi.
Este es el enemigo:
Editar en hoja de datos
Y para ocultarlo agregamos un Web Part Editor de Contenido e hicimos click en el botón Editar código fuente:
Content Editor Web Part Source Editor
Allí añadimos el script:
<script type="text/javascript" >
var allMenuItems = document.getElementsByTagName('ie:menuitem'); 
for(var i = 0; i < allMenuItems.length; i++ )   
{
 try
        {
         if (allMenuItems[i].text.toLowerCase() == "editar en hoja de datos")
         {
   var parentNodeOfMenuItem = allMenuItems[i].parentNode;  
                 parentNodeOfMenuItem.removeChild(allMenuItems[i]);                                
  }
 }
 catch(err)
 {}

} 
</script>

Puede parecer un poco desordenado, pero a SharePoint no le importará. Después hacemo click en guardar.
CEWP Source Editor Window
Después de eso podemos poner el web part oculto para que los usuarios no puedan verlo.
Y eso es todo.
Edit in Datasheet Hidden
Enjoy!

No hay comentarios:

martes, 14 de febrero de 2012

Métodos Extensores para Objetos Null

¿Es posible usar un método extensor en algo que es null?

Qué bonito sería poder hacer algo como:
if (!MyString.IsNull()) return MyString.ToString();
Leí hace unos cuantos años que hacer eso sería imposible porque, al ser el objeto null no podrías llamar al método o algo así… Pero en mi cabeza tenía sentido.

Así que me he estado conteniendo para no hacerlo todo este tiempo hasta hoy que me he sentido valiente.

Los métodos extensores:
public static bool IsNull(this string str)
{
    return str == null;
}

public static string ToStringSafe(this object obj)
{
    return (obj ?? string.Empty).ToString();
}
El método main obviamente todo buen programa de pruebas debe ser una aplicación de consola:
static void Main(string[] args)
{
    string str = null;

    if (str.IsNull())
        Console.WriteLine("It was null...");
    else
        Console.WriteLine("It wasn't null...");

    Console.WriteLine(str.ToStringSafe());

    Console.ReadKey();
}
¡Y funciona! Esto abre una nueva dimensión a mis recetas de espagueti.

El primer ejemplo útil que se me viene a la cabeza aparte del ToStringSafe y del ToInt, ToDateTime... ¡Mírame!, ¡No puedo parar! es:

/// 
/// Disposes the object if it's not null.
/// 
public static void DisposeSafe(this IDisposable DisposableObject)
{
    if (DisposableObject != null)
        DisposableObject.Dispose();
}
Con este método nunca más tendremos que preocuparnos de si el objeto es null o no. Todo se libera sin problemas.

A veces me asusta que me den tanta alegría estas cosas…

No hay comentarios:

jueves, 8 de septiembre de 2011

Web Part Proveedor de Filtro con un árbol Silverlight en un ModalDialog

Empecé con esto hace un par de días... No quería hacerlo, porque sabría que iba a ser doloroso... pero me obligaron... Y entonces pensé que sería un post perfecto para el blog por lo de painful.

Lo que queríamos conseguir era filtrar elementos en un List View Web Part por Entidad. En nuestra solución tenemos una jerarquía de entidades por lo que pensamos que sería buena idea que el web part mostrase la jerarquía como un árbol.
Bien, así que necesitamos un web part con un TreeView que sea capaz de mandar la entidad seleccionada como filtro a un LVWP. Fantástico. Lo hice... Y no le gustó a nadie. Lo querían en Silverlight y no solo eso, lo querían en una ventana pop up. Sip, me cogieron, nunca había hecho nada parecido pero, ¿Quién dijo miedo?

Es un montón de código, la mayor parte feo así que solo postearé la parte interesante (básicamente la parte relacionada con la comunicación entre las páginas y el Silverlight) y las URLs de donde cogí las ideas.
Lo primero es poner a funcionar un Filter Provider Web Part. Para ello seguí las instrucciones de aquí. Primero lo intenté con un IWebPartRow, pero no era lo que yo quería así que cambié a ITransformableFilterValues. Esta parte es bastante simple así que no comentaré nada más.
La segunda parte es crear una ventana emergente. Después de googlear si googlear te parece un palabro raro deberías escucharme decir overridar o rollupear un rato me enconté con este post, que me pareció un buen sitio para empezar. Mi código en el web part terminó así:

        protected override void OnLoad(EventArgs e)
        {
            if (Page.IsPostBack)
            {
                if (!string.IsNullOrEmpty(GetFormValue("HiddenEntityName")))
                {
                    Page.Session["SelectedEntityName"] = Page.Request.Form["HiddenEntityName"];
                    Page.Session["SelectedEntityID"] = Page.Request.Form["HiddenEntityID"];

                    RenderHeader();

                    //SelectedEntityText.Text = string.Format("{0}  ", Page.Request.Form["HiddenEntityName"], Page.Request.Form["HiddenEntityID"]);
                }
                else
                    RenderHeader();
            }

            string CurrentWeb = SPContext.Current.Web.Url;
            string height = "500";
            string width = "500";
            string page = "/_layouts/stratex/EntityTree.aspx";

            // use next line for direct with  between  and  
            string scrp = @"
                            ";

            Type t = this.GetType();
            if (!Page.ClientScript.IsClientScriptBlockRegistered(t, "bindWebserviceToAutocomplete"))
                Page.ClientScript.RegisterClientScriptBlock(t, "bindWebserviceToAutocomplete", scrp);
        }
Tuve problemas trayéndome los valores del ModalDialog. No era capaz de encontrar los ID ni los Titles de los controles porque son creados dinámicamente. El truco que usé fue crear dos campos ocultos en el CreateChildControls:
        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            ...

            Page.ClientScript.RegisterHiddenField("HiddenEntityName", "");
            Page.ClientScript.RegisterHiddenField("HiddenEntityID", "");

            ...
        }
Oye Chan, ¿Te has dado cuenta que podrías usar solo la sesión y olvidarte de los HiddenFields? No preguntes, te lo advierto…
La próxima parte es crear la página aspx para el modal dialog. La guardé en un directorio que me creé en _layouts. El código de la página quedó así:
<%@ Page Language="C#" Inherits="StratExFramework.EntityTree,StratExFramework,Version=2.2.0.0,Culture=neutral,PublicKeyToken=311246df7412ca98" %>

<html>
<head>
<title>Select Entity for filtering</title>
<script type='text/javascript'>
    function PassParameterAndClose(EntityName, EntityID) {

        window.returnValue = new Array( EntityName, EntityID) ;

        var version = parseFloat(navigator.appVersion.split('MSIE')[1]);
        if (version >= 7) 
            { window.open('', '_parent', ''); }
        else
            { window.opener = self; }

        window.close();
    }
</script>
</head>
<body></body>
</html>
También me creé una clase de code behind como puedes ver en la primera línea del aspx... :
    public class EntityTree : WebPartPage
    {
        string CurrentWeb;
        string SelectedEntityID;

        protected void Page_Load(object sender, System.EventArgs e)
        {
            CurrentWeb = Request.Params["CurrentWeb"];
            SelectedEntityID = Request.Params["SelectedEntityID"];
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            string Source = CurrentWeb + "/Lists/XAPLibrary/SilverlightEntityTreeSelector.xap";
            string SilverlightHeight = "515";
            string SilverlightWidth = "500";

            LiteralControl obj = new LiteralControl();
            obj.Text = "<object id='silverlightHost' style='height: " + SilverlightHeight + "; width: " + SilverlightWidth + @"; margin: 0; padding: 0;' data='data:application/x-silverlight-2,' type='application/x-silverlight-2'>
                            <param name='Source' value='" + Source + @"' />
                            <param name='MinRuntimeVersion' value='3.0.40624.0' />
                            <param name='Background' value='#FFFFFFFF' />
                            <param name='initParams' value='" +
                                string.Format("{0}={1}", "site", HttpUtility.UrlEncode(CurrentWeb)) +
                                string.Format(", {0}={1}", "selectedentityid", HttpUtility.UrlEncode(SelectedEntityID)) +
                                @"' />
                            </object>";
            this.Controls.Add(obj);
        }

        public override void VerifyRenderingInServerForm(Control control)
        {
            return;
        }
    }
Lo que hago aquí es coger los parámetros del entorno en donde se ejecuta el web part y pasárselos al Silverlight. Uso el CurrentWeb para decirle a los web services del Silverlight cual es el contexto y el SelectedEntityID para resaltar la entidad que fue seleccionada la última vez que se abrió la ventana modal. Este es el código del Silverlight.
namespace SilverlightEntityTreeSelector
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            Tree.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Tree_PropertyChanged);

            Tree.Show(string.Empty);
        }

        void Tree_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "SelectedEntityID")
                HtmlPage.Window.Invoke("PassParameterAndClose", Tree.SelectedEntityName, Tree.SelectedEntityID);
            else if (e.PropertyName == "TreeLoaded")
                if (Application.Current.Resources.Contains("selectedentityid"))
                    if (!string.IsNullOrEmpty(Application.Current.Resources["selectedentityid"] as string))
                        Tree.ChangeSelectedItemTo(Application.Current.Resources["selectedentityid"] as string);
        }
    }
}

Ya tenemos todos los componentes.
Esto funciona de la siguiente manera: Seleccionas una entidad en el árbol de Silverlight, luego el Silverlight llama a la función javascript de la ventana modal y que pasa los parámetros al web part padre y cierra el popup. Finalmente el web part manda el filtro al List View WebPar.
Si usas este código te faltarán algunos métodos, pero lo que quería compartir aquí es el método que he seguido para conseguirlo básicamente porque no quiero tener que volver a pensarlo si alguna vez me vuelven a pedir que haga algo parecido en el futuro.



Me encantaría enseñaros algunas fotos, pero los web parts no han sido retocados por las hábiles manos de Adam, nuestro diseñador, y se os podrían salir los ojos de las órbitas.

No hay comentarios:

lunes, 11 de julio de 2011

Error HTTP 500 (No authority could be contacted for authentication.) en SharePoint

Después de restaurar mi máquina virtual de desarrollo en una red diferente la de mi casa estaba recibiendo un error 500 al intentar conectar. La cosa era curiosa porque podía ver el sitio desde el server, pero no desde mi máquina física y sí, había comprobado que las IPs estuviesen bien. Lo primero que hice fue configurar el IE9 para que me enseñase los errores HTTP como a mi me gusta verlos de la manera "unfriendly”.

Para hacerlo fui a Tools –> Internet Options –> Advanced, y allí en el arbol debajo de Browsing Browsing desmarqué la opción de “Show friendly HTTP error messages”.

Después de eso pude ver que el problema que estaba teniendo conectando desde fuera era “No authority could be contacted for authentication.”. Aquí vi que la manera más simple de arreglar el problema era sacar el servidor del dominio y voverlo a meter.

Y funcionó... Por fin...

No hay comentarios:

viernes, 8 de julio de 2011

Escondiendo los List View web parts cuando están vacíos

Hoy me han pedido que esconda los List View web parts de la solución cuando están vacíos... No me gusta el javascript, pero era obviamente la solución más simple, así que le pregunté a Google y me mandó a este post.

Copié el código en un web part Editor de Contenido y funcionó más o menos, pero cuando intenté esconder también las cabeceras de las columnas y añadir un mensaje solo funcionaba para dos de los tres web parts que tenía en la página cosas veredes asi que después de buscar un ratito más en Google lo cambié a:

<script type="text/javascript">
 function HideEmptyWebParts()
 {
   var itemsfound = new Array;
   var elements = document.getElementsByTagName('*');
   for(var i=0;i<elements.length;i++)
   {
      if(elements[i].className == 'ms-vb')
      {
         itemsfound.push(elements[i]);
      }
   }
  
   for (var i=0;i<itemsfound.length;i++)
   {
       if (itemsfound[i].innerHTML.indexOf("There are no items to show in this view of the")>-1)
       {
                itemsfound[i].parentNode.parentNode.parentNode.parentNode.innerHTML="<div class='ms-vb'>Not enough data to produce a dashboard.</div>";
         
       }
   }
 }

_spBodyOnLoadFunctionNames.push("HideEmptyWebParts")
 
</script>

Y entonces sí que empezó a funcionar como esperaba.

No hay comentarios:

martes, 1 de febrero de 2011

Ni SharePoint ni SQL Server funcionan en Azure VM Role

Como ya sabréis los que me leéis he estado intentando que me dejaran participar en la beta del Azure VM Role, pues bien, he conseguido una entrevista con los encargados de darme el acceso y me han hecho la pregunta más temida... ¿Y tu eso para que lo quieres?

Mi idea era montar una granja en la nube con SQL y SharePoint de manera que pudiese usar SSIS, nuestro cubo de BI, Reporting Services y SharePoint.

Bien, pues me han comentado que "De momento es imposible" al parecer hay problemas de conectividad entre las máquinas de VM Role y no funcionan correctamente ni SharePoint ni SQL Server.

Consejo que me dan, que lo monte todo en Office 365. Pero claro, primero de todo, es imposible pronunciar Office 365 en inglés y segundo, ¿qué pasa con mi cubo y mis reporting services si no puedo sacar web services del sandbox de Office 365? pues que no pueden funcionar, con lo que me quedaría con la mitad de mi solución funcionando y la otra tristemente olvidada en el último rincón de mi disco duro.

Solución que me dan... que me espere hasta el verano.

Voy a intentar que mi jefe me de 6 meses de vacaciones, pero si esto no funciona voy a tener que buscarme otro sitio en donde montar mi granja.

Ah y, por si alguien lo dudaba, al final no me han dado acceso al beta program.


Y los de Google mientras tanto  regalando portátiles para que la gente pruebe el Chrome OS...

No hay comentarios:

viernes, 3 de diciembre de 2010

Copiando ListViewWebParts entre diferentes sitios con sus correspondientes vistas personalizadas

Por un segundo he dudado si escribir el resto del post en el título.

En otro ejemplo de lo que ahora he dado en llamar Guerrilla Coding gracias a mis asombrosos conocimientos de la lengua que se habla en la pérfida Albión ahora puedo usar palabras como guerrilla en un par de horas tuve que hacer un programita para copiar cientos de páginas llenas de ListViewWebparts cada uno con su vista personalizada. Yo no sé vosotros, pero yo cada vez que tengo que tocar el ListViewWebpart me pongo a temblar...

Los ListViewWebparts crean en la lista de la que son "hijos" una vista Oculta cuando nosotros personalizamos la vista del webpart. Esto implica que para copiar los webparts a otro sitio tendremos que copiar las vistas en la lista del sitio de destino y apuntar al webpart a la nueva vista, no sé si me explico bien... mejor pondré un trozo de código...

Aquí lo que hago es copiar los webparts de cada fichero de origen al de destino, y les doy un tratamiento especial si son ListViewWebpart para esta aplicación es suficiente.

private static void CopyWebParts(SPFile origFile, SPFile destFile)
        {
            SPLimitedWebPartManager origWpm = origFile.GetLimitedWebPartManager(PersonalizationScope.Shared);
            SPLimitedWebPartManager destWpm = destFile.GetLimitedWebPartManager(PersonalizationScope.Shared);

            DeleteWebparts(destWpm);

            foreach (Microsoft.SharePoint.WebPartPages.WebPart webpart in origWpm.WebParts)
            {
                Microsoft.SharePoint.WebPartPages.WebPart newWp;

                if (webpart is ListViewWebPart)
                    newWp = UpdateListViewWebPart(webpart as ListViewWebPart, origFile.GetWeb(), destFile.GetWeb());
                else
                    newWp = webpart;

                destWpm.AddWebPart(newWp, Common.ConvertToString(newWp.ZoneID), newWp.ZoneIndex);
            }

            try
            {
                destFile.Publish("Added Web Parts");
                destFile.Approve("Web Part additions approved");
            }
            catch { }
        }

        private static ListViewWebPart UpdateListViewWebPart(ListViewWebPart webpart, SPWeb origWeb, SPWeb destWeb)
        {
            ListViewWebPart newWebPart = webpart; //yeah I know.

            string oldListName = webpart.ListName;
            string oldViewGuid = webpart.ViewGuid;

            SPList OrigList = origWeb.Lists.GetList(new Guid(oldListName), true);
            
            SPList DestList = destWeb.Lists[OrigList.Title];

            SPView OrigView = OrigList.GetView(new Guid(oldViewGuid));
            SPView DestView = DestList.Views.Add(string.Empty, OrigView.ViewFields.ToStringCollection(), OrigView.Query,
                OrigView.RowLimit, OrigView.Paged, OrigView.DefaultView);
            DestView.Hidden = OrigView.Hidden;
            DestView.Scope = OrigView.Scope;
            DestView.ApplyStyle(destWeb.ViewStyles.StyleByID(Convert.ToInt32(OrigView.StyleID)));

            DestView.Update();

            newWebPart.ViewGuid = DestView.ID.ToString("B").ToUpper();
            newWebPart.ListName = destWeb.Lists[OrigList.Title].ID.ToString("B").ToUpper();


            return newWebPart;
        }
Y, contra todo pronóstico, funcionó... Espero no tener que tocar estos webparts otra vez en mucho tiempo.

No hay comentarios:

viernes, 17 de septiembre de 2010

Lambdas, Method Extensions y RunWithElevatedPrivileges

A estas alturas ya no es un problema para nadie abrir un sitio como administrador independientemente del usuario que este logueado, sin embargo, quiero proponer una función que me parece bastante útil.
/// 
        /// Returns a NEW site with full permissions
        /// 
        public static SPSite OpenSiteWithElevatedPrivileges(this SPSite site)
        {
            SPSite newSite = null;

            SPSecurity.RunWithElevatedPrivileges(() => newSite = new SPSite(site.ID));

            return newSite;
        }
Resulta cómodo, ¿no? A mí me gusta hacer
SPSite site = SPContext.Current.Site.OpenSiteWithElevatedPrivileges();
¿Qué opináis?

No hay comentarios:

lunes, 22 de febrero de 2010

Búsqueda por propiedades administradas desde parámetros en la URL

Para hacer mi nube de tags mi objetivo primario era trabajar lo menos posible aprovechar al máximo las posibilidades que nos brinda MOSS y para lograrlo, en tema de búsquedas, es primordial encontrar la forma de pasarle tu consulta a la página de resultados de búsqueda en la URL.


Al principio me desanimé bastante porque yo quería usar una clave al estilo k= o s= para las propiedades administradas, pero como seguramente habrás notado no la hay.


Por cierto aprovecho para enumerar los parámetros que conozco y así no se me olvidan:



  • k: Es la consulta en texto libre que mandamos al motor,


    • /Results.aspx?k=Hola

  • s: Es el ámbito en el que vamos a buscar nuestra consulta,


    • /Results.aspx?k=Hola&s=Todos%20los%20sitios

  • v: Orden de resultados,


    • Results.aspx?k=Hola&s=Todos%20los%20sitios&v=date (o también relevance)

  • start: Número del primer elemento que se mostrará en los resultados (útil para paginar),


    • /Results.aspx?k=Hola&s=Todos%20los%20sitios&&v=relevance&start=21

Con esto ya tenemos para ir tirando, pero no me servía de nada para mi nube de tags. ¿Qué podía hacer? pues le pregunté a mi compañero Igor, que está haciendo un proyecto de búsquedas facetadas. Inmediatamente me dio la solución.


Para buscar por propiedades administradas tan solo tenemos que hacer la consulta de este modo:


k=PropiedadAdministrada:Valor


Qué fácil va a ser ahora apuntar las consultas mediante links aprovechando el motor de búsquedas de MOSS y qué poco trabajo me costó preguntar.

1 comentario:

jueves, 11 de febrero de 2010

Mantenimiento de página de elemento Web o Web Part Page Maintenance

Ya se que todo esto ha salido en mil blogs y que cada vez que ha salido ha sido replicado a su vez en mil foros 1000x1000 que gracias a mi pasarán a ser 1000x1000 + 1x0, pero el caso es que a mi se me sigue olvidando y para no volver a perder ni un segundo más en encontrarlo lo posteo. Además estoy seguro de que a más de uno también le pasa.

Se trata de una página que proporciona SharePoint y que sirve para enumerar los webparts que hay ejecutándose en una página, tanto los que se ven como los que cerraste en lugar de eliminarlos y se te quedaron ahí ad eternum.

Esto sirve muy bien si eres un manazas y agregas un webpart que cuelga la página o bien que hace que sea imposible la edición y no puedes borrarlo por el método tradicional de Edición –> Eliminar.

Gracias a esta página y sin olvidarnos de pulsar antes el botón desproteger, nos será muy facil librarnos de esos webparts que nadie puede ver, pero que nosotros sabemos que están ahí o bien de esos otros que son tan visibles que ocultan al resto.

Mantenimiento de página de elementos Web

Y ahora viene el motivo del post y de varios minutos perdidos tontamente por internet.

¿Cómo llegamos a esta página? Pues es muy simple, a la URL de nuestra página que está dando el error o bien que queremos auditar le añadimos ?contents=1

?contents=1

Es muy simple, pero como tampoco es una cosa que haga todos los días pues siempre se me olvida.

Y ya para rematar el post, no me puedo resistir…

¡Los suspiros son aire y van al aire!
¡Las lágrimas son agua y van al mar!
Dime, blogger, cuando un webpart se cierra
¿sabes tú adónde va?

Pues a la página de mantenimiento de webparts, Gustavo que eres muy antiguo.

3 comentarios:

lunes, 18 de enero de 2010

Viajando en el tiempo con una nube de tags

Vaya tela, escribo este post para tapar un poco el de antes y me sale este título, no tengo remedio, soy un impresentable.

Bueno, a lo que vamos. Estamos haciendo unos desarrollos para hacer de MOSS un facebook ¿ahora que ya está aquí SP2010? sí ahora.Y entre otras cosas como comentarios a las publicaciones y valoraciones se nos requería una nube de tags.

Delante de un Croissant a la plancha nos planteamos la estrategia para realizar semejante proeza sin par y se nos ocurrió que para llevar el conteo de ocurrencias de cada tag en la web íbamos a tener una lista en el sitio raíz y allí actualizaríamos cada vez que alguien hiciese checkin del elemento. En nuestro caso nos venía de perlas suscribirnos al evento ItemCheckedIn porque lo que necesitamos categorizar taggear pa ti y pa mi son páginas de publicación, pero ¿Cómo puedo actualizar los valores de la lista de tags? Si simplemente sumo uno a la lista de tags y no borro el antiguo no tendré una lista consistente… Necesitamos saber cuál había marcado justo antes del checkin.

Pues nos creamos un método extensor basado en las versiones anteriores del elemento y podremos conocerlo sin problemas.

public static string PreviousValueInHystory(this SPListItem item, string fieldName)
{
Object obj = null;

if (item.Versions.Count > 0)
obj = item.Versions[0][fieldName];

if (obj == null)
return string.Empty;
else
return string.IsNullOrEmpty(obj.ToString()) ? string.Empty : obj.ToString();
}

Por cierto, si os suscribís al ItemCheckedIn tendreis que cambiar el Versions[0] por Versions[1] porque el cero será el que acabáis de crear en el mismo momento de llamar al método.

No hay comentarios:

miércoles, 18 de noviembre de 2009

AvailableWebTemplates en el site definition

Desde el onet.xml de un site definition es fácil cambiar las plantillas de sitio disponibles de que tendrá en el menú de creación de sitios hijos. Simplemente habrá que añadir los sitios que necesitemos en la propiedad AvailableWebTemplate de la característica de Publishing del sitio:

<Feature ID="22A9EF51-737B-4ff2-9346-694633FE4416">
..
<Property Key="AvailableWebTemplates" Value="*-MYTEMPLATE#0" />
..
</Feature>

Y el Value se traduce en [LCID]-[TEMPLATE] de esto podemos deducir que *-MyTemplate no quiere decir todos los templates menos el mío si no que los templates disponibles serán los MyTemplate de cualquier idioma.

También podemos permitir más de un template disponible si los separamos por ;

<Property Key="AvailableWebTemplates" Value="*-MYTEMPLATE#0;*-YOURTEMPLATE#0" />

Y ahora solo falta acertar con el nombre correcto del template :) o no saldrá nada…

No hay comentarios:

viernes, 30 de octubre de 2009

El ViewState se pierde extendiendo el ContentByQueryWebPart

Pues parece que nuestro amigos han vuelto a hacer de las suyas al programar el CQWP y han pensado que es una gran idea cargarse el viewstate. Asi que cuando tú inocentemente le añades tu variable la próxima vez que se carga el webpart te das cuenta de que ha desaparecido mágicamente.

Bueno, la solución parcial que hemos encontrado es sobreescribir los métodos SaveViewState y LoadViewState por aquello de quedar por encima.

No es demasiado elegante, pero sí muy efectivo:

        public string Filter { get; set; }

protected override object SaveViewState()
{
object[] myViewState = new object[2];
myViewState[0] = base.SaveViewState();
myViewState[1] = Filter;

return myViewState;
}

protected override void LoadViewState(object savedState)
{
object[] myViewState = null;
if (savedState != null)
{
myViewState = (object[])savedState;
base.LoadViewState(myViewState[0]);
Filter += (string)myViewState[1];
}
}

Espero haber sido más rápido que Luis en postear, jijijiji

No hay comentarios:

lunes, 26 de octubre de 2009

Creación de usuarios de FBA programáticamente

El otro día tuve que hacer una instalación de un FBA y se me ocurrió que no tenía ganas de usar el asistente de Visual Studio eso o que no tenía un Visual Studio a mano… total que se me metió en la cabeza que debía de ser facilísimo crear los usarios programáticamente. Claro, desde el portal no tiene ningún secreto, pero yo lo que quería era hacerlo desde una aplicación de consola.

Al final,como siempre, no me resultó trivial pese a ser facilísimo, y como no lo tengo subido al TFS y yo soy de los que se olvidan de este tipo de cosas, lo subo al blog.

El main no tiene ninguna complicación, se crea el usuario con un Membership.CreateUser y ser recoge el resultado de la operacion en un MembershipCreateStatue, así:


static void Main(string[] args)
{
System.Web.Security.MembershipCreateStatus Creado;
System.Web.Security.Membership.CreateUser(args[0], args[1], args[2],
Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), true, out Creado);

Console.WriteLine(Creado.ToString());
Console.ReadKey();
}

Claro, qué fáci :) pero ¿cómo sabe el Membership a dónde apuntar? pues se lo tenemos que decir añadiendo a nuestra solución un “Archivo de Configuración de Aplicación”. Yo como soy tremendamente original lo llamé App.config.


Y en este fichero .config es donde tenemos que definir todos los datos de nuestro Membership Provider. Para regocijo de todos, se puede sacar la configuración directamente desde el web.config de la aplicacion web donde tenemos montado la infraestructura del Form Based Authentication. Os pego una copia esquemática de lo que hay que añadir:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="NOMBREDELACONEXION" connectionString="server=INSTANCIA;database=BASEDEDATOS;Trusted_Connection=true" />
</connectionStrings>
<system.web>
<membership defaultProvider="NOMBERDELMEMBERSHIPPROVIDER">
<providers>
<add connectionStringName="NOMBREDELACONEXION" applicationName="/"
name="NOMBERDELMEMBERSHIPPROVIDER"
type="CLASE, ASSEMBLY, Version=X.X.X.X, Culture=neutral, PublicKeyToken=KEY" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="NOMBREDELROLEPROVIDER">
</roleManager>
</system.web>
</configuration>

Y con esto ya funciona mágicamente.


Suerte!

No hay comentarios:

martes, 5 de mayo de 2009

An error has occurred in the script on this page

[EDIT: Lee los comentarios antes de seguir este método]

Hoy se me ha dado este caso, y no es la primera vez que veo esto, así que post al canto.

Internet Explorer Script Error


Line: 3031
Char: 2
Error: ‘RTE_ToggleEnableShortcuts’ is undefined
Code: 0
Y el fichero que nos canta es el /_layouts/1033/HtmlEditor.js

El error se nos produce al teclear en una ventana de editor de texto enriquecido de un webpart editor de contenido.

¿No os ha ocurrido un error parecido a esto? si trabajáis con portales en “en-US” os pasará.

Tras darnos un paseito por /layouts/1033 y mirar las fechas de los ficheros js comparándolos con los de, por ejemplo, /layouts/3082 nos damos de que hay ciertos ficheros que no están actualizados…

En este momento podemos hacer dos cosas, solucionarlo por la vía rápida o leer un poco sobre el tema.

Leyendo un poco sobre el tema nos enteraremos de que dependiendo de si instalas el sharepoint con el SP1 o si instalas el sharepoint y luego pasas el update estos ficheros pueden no estar actualizados y que hay que hacerlo a mano.

Y ahora lo solucionamos por la vía rápida: copiamos desde el directorio 3082 al 1033 todos estos ficheros nuevos:

  • FORM.JS
  • INIT.JS
  • CORE.JS
  • BFORM.JS
  • OWS.JS

Hacemos el IISRESET de rigor y a teclear.

Saludos.

3 comentarios:

jueves, 26 de febrero de 2009

Asignar palabras como ruido (noise) en las búsquedas

Hay ocasiones en que no queremos permitir que se busque por una palabra determinada podemos decirle a SharePoint que esa palabra es ruido de forma que se la omita en las consultas que se realicen al motor y no devuelva nada.

Por ejemplo, no queremos que cuando alguien busque por el nombre de nuestro dominio "DOMAIN" se le muestren todas las páginas, ¿Qué hacer?

Nos vamos a C:\Archivos de programa\Microsoft Office Servers\12.0\Data\Office Server\Applications\<GUID>\Config y allí editamos el fichero noiseesn.txt añadimos al final la palabra DOMAIN (por cierto no es case sensitive) y guardamos.

Para que tenga efecto nuestra modificación hacemos un net stop osearch y un net start osearch y ya podemos probar. Con un poco de suerte obtendremos este resultado:

image

Prueba superada, y esto está bien, pero los diccionarios (thesaurus) son bastante más potentes, tengo que hacer otro post al respecto.

Editar el noiseneu.txt no parece tener ningún efecto se ve que hace realmente honor a su nombre y es neutral, una pena en los portales multiidioma...

No hay comentarios:

miércoles, 18 de febrero de 2009

xhtml 1.0 strict en SharePoint es posible

Tras pasar las validaciones WAI-AA y XHTML con el Total Validator y con el TAW me dispuse a pasarlas también con el validator del W3C, pero cuál sería mi sorpresa al darme cuenta de que precisamente con éste último no valida...

Tras decirle que me mostrase el código fuente me fijé en que el renderizado que estaba mandando SharePoint al validator.w3.org no era el mismo que el que mandaba a Explorer, Firefox, Opera, Safari etc. (Faltaba un "div"; debajo del "form" y, al no estar contenidos, todos los "inputs" se entendían como erróneos). Esto me hizo pensar en que debía añadir un "browser" específico para el "analizador".



Y tras un ratito charlando con mi amigo google encontré un par de browsers que, tras mezclarlos entre si quedaron:


<browser id="w3cValidator" parentID="default">
<identification>
<userAgent match="^W3C_Validator" />
</identification>
<capture>
<userAgent match="^W3C_Validator/(?'version'(?'major'\d+)(?'minor'\.\d+)\w*).*" />
</capture>
<capabilities>
<capability name="browser" value="w3cValidator" />
<capability name="majorversion" value="${major}" />
<capability name="minorversion" value="${minor}" />
<capability name="version" value="${version}" />
<capability name="ecmaScriptVersion" value="1.2" />
<capability name="javascript" value="true" />
<capability name="supportsCss" value="true" />
<capability name="tables" value="true" />
<capability name="xml" value="true" />
<capability name="w3cdomversion" value="1.0" />
<capability name="tagWriter" value="System.Web.UI.HtmlTextWriter" />
</capabilities>
</browser>


No fue suficiente, pero ya lo tuve fácil. Faltaba añadir en el web.config, debajo del <system.web>

<xhtmlConformance mode="Strict" />

Para finalizar, un leve toque de iisreset y listo.


A disfrutar del Congratulations!


Todo lo que podais porque entre unas cosas y otras dura poco

No hay comentarios:

miércoles, 28 de enero de 2009

Configurando el IFilter de Adobe para PDF en x64

Vaya, pues resulta que lo sacaron en diciembre del 2008 y ni me había enterado qué raro cuando yo estoy pulsando ctrl+f5 cada 10 segundos en la web de adobe por si acaso.

Ya había perdido la esperanza después de los años que han tardado, pero al final lo han sacado haciendo así realidad la peor pesadilla de los de Foxit que por muy bien que vaya no es gratis.

Sin más dilación paso a presentarles...

El tan esperado Adobe PDF iFilter 9 para plataformas de 64-bits

Voy a instalarlo a ver qué tal y os cuento.

... me lo bajo ... lo subo ... descomprimo ... doble click ... Math.Pow(Next,n) ... Close

Por otro lado me voy a la administración de búsquedas del SSP, Tipos de archivo y añado el PDF.

Paso de la henna de ponerle el iconito :P

Como siempre hago un Restablecer todo el contenido rastreado, por qué no, un un toquecito de iisreset y luego los consabidos net stop osearch, net stop spsearch, net start spsearch y net start osearch para luego hacer un rastreo completo y rezar mientras se completa.

Hago una búsqueda para probar y... nada :(

Me leo las instrucciones del ifilter y me dice que tengo que agregar al path el directorio bin, así que Panel de control, Sistema, Opciones avanzadas, Variables de entorno y a la Variable de sistema Path le añado al final ;C:\Archivos de programa\Adobe\Adobe PDF iFilter 9 for 64-bit platforms\bin

Para intentar ahorrarme el reinicio añado el path a mano, y vuelvo a crawlear, pero nada :(

La desesperación se apodera de mi y me decido a leerme las instrucciones, pero cual no sería mi sorpresa al darme cuenta de que el fichero de instrucciones que hay alojado en la página de Adobe conduce a un PDF que no se puede leer... bueno pues a buscar otro poco.

Despues de un ratito dando vueltas encontré en el blog de Alexander un señor muy respetable a juzgar por la foto, un link al dichoso manual colgando de un servidor que no es el de Adobe si no queréis ir os ahorro el viaje al blog Configuring PDF iFilter for MS Sharepoint 2007.pdf.

Vale, antes de nada hago una copia del registro que nunca está de más y sigo las instrucciones... y reestablezco y rastreo y rezo y nada :'(

Y ya claro, me termino por enfadar y como ya había hecho una copia del registro pues en un arrebato berserker me fui a la parte más alta del arbol del registro y desde allí me dediqué a buscar y reemplazar todas las apariciones de la cadena {4C904448-74A9-11D0-AF6E-00C04FD8DC02} por la que nos aconsejan en las instrucciones {E8978DA6-047F-4E3D-9C78-CDBE46041603}... y reestablezco y rastreo y rezo y ...

¡¡CONSEGUIDO!!

Pero el resultado de la búsqueda queda muy feo sin el iconito de PDF... venga se lo añado ¿En los demás frontends también? si, en todos.

Por cierto, para no tener problemas con los de Adobe más nos vale usar su iconito corporativo, lo podemos bajar de aquí.

Enhorabuena a los de Adobe que han sabido responder ágilmente a las súplicas de toda la comunidad, es una suerte que todavía no se haya inventado ninguna forma de escribir en el registro con un instalador y nos brinden la oportunidad de hacerlo nosotros manualmente. Enhorabuena también por el esmero que han puesto para regalarnos a los que no somos de los EEUU este acertijo extra ¿Os funciona sin hacer lo de el reemplazo en el registro?

Y mis condolencias a los de foxit.

Soy el peor... pa lo que me ha costao, encima con exigencias...

<edit>NOO00o, al día siguiente probé y no buscaba :( finalmente deshice el cambio de los guids y reinstalé el ifilter y sorprendentemente funcionó, esto me pasa por postear sin dejar pasar dos meses de garantía</edit>

No hay comentarios:

miércoles, 14 de enero de 2009

Un listado de SharepointWebControls

El otro día me volvió a pasar que no encontraba el nombre de un control para una columna de SharePoint al escribir un layout. Como es natural busqué un poco en los foros y me encontré con una entrada de Hezser sobre How to use the SharePoint Web Controls.


Qué pedazo de entrada... y encima, no es de esos que publica en su idioma, el tío lo hace en inglés para que todo el mundo pueda leerlo sin problemas, todos los bloggers deberían de aprender de él.

Esta tabla me ha servido además para lo que estoy haciendo hoy por lo que se la voy a plagiar, un poquito solo:

Columna tipo

Nombre del control

Una línea de texto

SharepointWebControls:TextField

Texto plano

SharepointWebControls:NoteField

Texto enriquecido

SharepointWebControls:RichTextField

Texto enriq. mejorado

SharepointWebControls:RichTextField

Menú desplegable

SharepointWebControls:DropDownChoiceField

Menú elección

SharepointWebControls:RadioButtonChoiceField

Número

SharepointWebControls:NumberField

Moneda

SharepointWebControls:CurrencyField

Fecha y hora

SharepointWebControls:DateTimeField

Búsqueda (simple)

SharepointWebControls:LookupField

Búsqueda (múltiple)

SharepointWebControls:MultipleLookupField

Sí/No

SharepointWebControls:BooleanField

Persona o grupo

SharepointWebControls:UserField

Enlace o foto

SharepointWebControls:UrlField

Calculado

SharepointWebControls:UrlField

En su sitio explica además cómo usarlos en C#, muy aconsejable, si señor.

No hay comentarios:

jueves, 18 de diciembre de 2008

HRESULT: 0x80070094 ¿Pero de qué te quejas ahora SharePoint?

En mi caso SharePoint daba este error al intentar crear una nueva aplicación web. Nada, nada, tranquilididad. Se trata de el servicio de administración de IIS no está funcionando como Dios manda. Para comprobar que se trata de esto nos vamos a Inicio --> Herramientas administrativas --> Administración de Internet Information Services (IIS) y vemos que no rula.


Solución: Rápido y veloz nos vamos a Ejecutas: services.msc y buscamos el servicio llamado "Servicio de administración IIS" pulsamos reiniciar, aceptar y listo.


Si esto no funciona podemos reiniciar el server completo, y si eso tampoco surte efecto dicen que hay un hotfix de Microsoft que se encarga del tema. A mi me bastó con el reinicio del servicio. Al final tuve que resetear todos los web front end :(


Por cierto, si alguien me ha echado de menos es que he estado malito con conjuntivitis.

No hay comentarios: