MOSS / Servidor de formularios de InfoPath (InfoPath 2007) rendimiento de la lista desplegable

Categoría adicional: InfoPath

Resumen: Un InfoPath 2007 forma implementado en un servidor MOSS proporciona una lista desplegable de los proveedores vinculados a una lista personalizada de MOSS. Al seleccionar un proveedor, reglas de asignan los valores de campo a un puñado de campos de texto como el nombre del representante de ventas, Dirección, ciudad, estado, postal y teléfono. El rendimiento es horrible. Nos damos cuenta que peor desempeño (de una manera no lineal) para cada campo adicional actualizamos esta manera. Es decir, Si acabamos de actualizar el nombre del representante de ventas, Toma [x] cantidad de tiempo. Si actualizamos representante de ventas, Address1, destinatario2, ciudad, estado, zip, Toma 10 veces más.

Solución: Escribir un servicio web (Código de ejemplo puede encontrarse aquí) Eso es pasado en nombre de un proveedor y vuelta devuelve los detalles del vendedor. A continuación, asignar los campos de esta manera. Aunque esto parece demasiado lento, No había ninguna diferencia discernible en el rendimiento cuando asignamos 1 campo versus 8 campos. Como un bono adicional, los usuarios obtienen un fresco "ponerse en contacto con el servidor" Cylon resultados del efecto mientras esperan el formulario para invocar y consumir el servicio.

MOSS: Se produjo una excepción. (Excepción de HRESULT: 0x 80020009 (DISP_E_EXCEPTION))

ACTUALIZACIÓN: Nunca se determinó la causa de este problema y nunca superficie nuevamente.

Notamos que de repente durante la implementación de un sitio de desarrollo, dos usuarios son incapaces de tener acceso a una colección de sitios. Estas cuentas pueden autenticarse en el sitio principal, pero al intentar acceder a una colección particular de sitio, acaba de llegar una pantalla en blanco. No muestra los errores, sólo una página en blanco en blanco.

Nos inicie sesión como un administrador de la colección de sitios e intentar agregar uno de estos usuarios como un administrador de sitio y esta vez, al pulsar "Aceptar", recibimos este mensaje:

Se produjo una excepción. (Excepción de HRESULT: 0x 80020009 (DISP_E_EXCEPTION))

Pasamos algún tiempo investigando esto y lamentablemente, no llegar a nada útil. Hubo algunos mensajes en el registro de diagnóstico, pero era difícil exactamente se correlacionan con este problema.

En el final, eliminar la colección de sitios y vuelve a crear y que resolvió.

Si averiguar qué causó en el futuro, Podrá actualizar este post.

MOSS: Iterar a través de listas personalizadas y devolver datos filtrados a InfoPath

Escenario de negocio:

Proporcionar un método que permite a los usuarios entrar en las requisiciones de compra precisa rápidamente.

Problema del negocio:

El cliente hace negocios con varios proveedores de cien.

Los vendedores son "tipo" específicos. Esto significa que el vendedor vende equipos informáticos (por ejemplo:. Dell) o suministros de oficina (por ejemplo:. Staples).

Cómo nos permiten a los usuarios finales que crean Seleccione las requisiciones de compra un vendedor válido?

Solución de negocio:

Distinguir los vendedores en el sistema a través de "tipo".

Permiten a los usuarios seleccionar el "tipo" de producto proporciona un conjunto filtrado de proveedores adecuados.

Solución técnica:

Se ha diseñado un formulario de InfoPath que permite a los usuarios entrar en línea requisiciones de compra.

Selección de proveedores de control de dos listas de selección de InfoPath. Primero, el usuario selecciona un tipo de"compra". Esto limita una segunda lista de selección para contener solamente los proveedores que venden para ese tipo de compra. Se trata de un desplegable en cascada clásico.

Los vendedores se almacenan en una lista personalizada de MOSS con columnas personalizadas para los atributos como nombre proveedor, Dirección y sobre todo "tipo".

Implementar un servicio web para un cliente de InfoPath consumir itera a través de la lista de proveedores personalizados, devolver sólo los proveedores que empareja un "tipo" proporcionado.

Invocar el servicio web mediante el formulario de InfoPath.

Lecciones aprendidas:

  • Primero, Parece necesario seguir esta ruta. Hubiera preferido hacer el filtrado completamente dentro de InfoPath y no crea ninguna funcionalidad de servicio web aquí. Sin embargo, servidor de formas no proporcionan la funcionalidad de filtrado requerida. Podemos poner una regla en un tipo"" lista de selección en la forma de una especie de volver a abrir la consulta de proveedores, Pero no podemos hacerlo para que funcione correctamente. Por lo tanto, era necesario implementar el servicio web.
  • Este es una clásico "en cascada lista de selección" problema en el InfoPath forma mundial de servidores y hay muchos buenos ejemplos por ahí que explican cómo resolver esto.
  • Un valor en blanco para una columna en la lista de proveedores no devuelve una cadena vacía cuando se hace referencia como esta: initItem["Nombre del proveedor"]. En su lugar, Devuelve un valor null.

Algunas otras notas:

  • Vuelva una matriz[] de los vendedores porque tenía cierta dificultad devolver una lista de matrices. InfoPath se quejó de ello y no tuve el tiempo ni la inclinación a pelear por él. Esto, Claro, pone un límite artificial sobre el número total de proveedores. También me obligó a aplicar un recorte() método de la matriz porque odio la idea de volver atrás 100 vendedores null. InfoPath no le importa, Pero daba la lata a mí. (Nuevo, Esto era más fácil que InfoPath peleando ArrayLists).
  • Implementé un GetSpecificVendorByName() así como la función, que puede ser instructivo.

El código:

utilizando Sistema;
utilizando System.Web;
utilizando System.Web.Services;
utilizando System.Web.Services.Protocols;
utilizando Microsoft.SharePoint;
utilizando System.Configuration;

/// <Resumen>
///
Proveedor servicio: Proporciona el proveedor relacionados con servicios que hoy son consumidos por un formulario de cliente de infopath.
///
/// Historia:
/// ——–
/// 07/24/07: Inicial de codificación, Paul J. Gavin de Conchango.
///
/// </Resumen>
[WebService(Namespace = "http://www.conchango.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
público clase VendorService : System.Web.Services.WebService
{

/// <Resumen>
/// Representa un proveedor de una lista personalizada de sharepoint MSUSA.
/// </Resumen>
público clase Proveedor
{
público Proveedor() { }

público Proveedor(SPItem initItem)
{
Si (! (initItem["Nombre del proveedor"] == NULL)) NombreDeProveedor = initItem["Nombre del proveedor"].ToString();
Si (! (initItem["Dirección 1"] == NULL)) VendorAddress1 = initItem["Dirección 1"].ToString();
Si (! (initItem["Dirección 2"] == NULL)) VendorAddress2 = initItem["Dirección 2"].ToString();
Si (! (initItem["La ciudad"] == NULL)) VendorCity = initItem["La ciudad"].ToString();
Si (! (initItem["VendorPhone"] == NULL)) VendorPhone = initItem["VendorPhone"].ToString();
Si (! (initItem["PurchaseType"] == NULL)) VendorType = initItem["PurchaseType"].ToString();
Si (! (initItem["Estado"] == NULL)) VendorState = initItem["Estado"].ToString();
Si (! (initItem["Zip"] == NULL)) VendorZip = initItem["Zip"].ToString();
Si (!(initItem["Fax"] == NULL)) VendorFax = initItem["Fax"].ToString();
Si (!(initItem["SalesRepName"] == NULL)) VendorSalesRepName = initItem["SalesRepName"].ToString();

VendorItemId = initItem.ID; // ID único gracias a MOSS.
}

público int VendorItemId;
público cadena NombreDeProveedor;
público cadena VendorAddress1;
público cadena VendorAddress2;
público cadena VendorCity;
público cadena VendorState;
público cadena VendorZip;
público cadena VendorPhone;
público cadena VendorType;
público cadena VendorSalesRepName;
público cadena VendorFax;
}

público VendorService () {

//Descomentar la siguiente línea si utiliza componentes diseñados
//InitializeComponent();
}

privada Proveedor[] GenerateTestVendors()
{
Proveedor[] resultList;
resultList = Nuevo Proveedor[100];

Proveedor v;
v = Nuevo Proveedor();
v.VendorAddress1 = "v1_address1";
v.VendorAddress2 = "v1_address2";
v.VendorCity = "v1_city";
v.VendorName = "v1_vendorname";
v.VendorPhone = "v1_vendorphone";
v.VendorState = "v1_st";
v.VendorType = "v1_type";
v.VendorZip = "v1_zip";

resultList[0] = v;

v = Nuevo Proveedor();

v.VendorAddress1 = "v2_address1";
v.VendorAddress2 = "v2_address2";
v.VendorCity = "v2_city";
v.VendorName = "v2_vendorname";
v.VendorPhone = "v2_vendorphone";
v.VendorState = "v2_st";
v.VendorType = "v2_type";
v.VendorZip = "v2_zip";

resultList[1] = v;

v = Nuevo Proveedor();
v.VendorAddress1 = "v3_address1";
v.VendorAddress2 = "v3_address2";
v.VendorCity = "v3_city";
v.VendorName = "v3_vendorname";
v.VendorPhone = "v3_vendorphone";
v.VendorState = "v3_st";
v.VendorType = "v3_type";
v.VendorZip = "v3_zip";

resultList[2] = v;

retorno resultList;

}

[WebMethod]
público Proveedor GetSpecificVendorById(int Identificador)
{
cadena SpVendorSiteName; // Nombre del Real Sitio MOSS que aloja la lista de proveedores de encargo.
cadena SpVendorListName; // Nombre de la actual lista de musgo proveedores.

SpVendorSiteName = ConfigurationSettings.AppSettings["VendorListHostingSite"].ToString();
SpVendorListName = ConfigurationSettings.AppSettings["VendorList"].ToString();

utilizando (SPSite sitio = Nuevo SPSite(SpVendorSiteName))
{

utilizando (SPWeb Web = página. OpenWeb())
{

SPList currentList = web. Listas de[SpVendorListName];

SPItem specificItem = currentList.Items[Identificador];

retorno Nuevo Proveedor(specificItem);

} // uso de spweb web = site.openweb()
} // uso de spsite site = new spsite("http://localhost/mizuho")

}

[WebMethod]
// Se supone que el nombre del proveedor es único, desde una perspectiva empresarial
público Proveedor GetSpecificVendorByVendorName(cadena ser)
{
cadena SpVendorSiteName; // Nombre del Real Sitio MOSS que aloja la lista de proveedores de encargo.
cadena SpVendorListName; // Nombre de la actual lista de musgo proveedores.

SpVendorSiteName = ConfigurationSettings.AppSettings["VendorListHostingSite"].ToString();
SpVendorListName = ConfigurationSettings.AppSettings["VendorList"].ToString();

utilizando (SPSite sitio = Nuevo SPSite(SpVendorSiteName))
{
utilizando (SPWeb Web = página. OpenWeb())
{

SPList currentList = web. Listas de[SpVendorListName];

foreach (SPItem vendorItem en currentList.Items)
{
Si (vendorItem["Nombre del proveedor"] == NULL) «««;

Si (vendorItem["Nombre del proveedor"].ToString().Es igual a(ser))
retorno Nuevo Proveedor(vendorItem);
}

Proveedor v = Nuevo Proveedor();
v.VendorPhone = "no se encuentra: " + ser;

retorno v;

retorno NULL;

} // uso de spweb web = site.openweb()
} // uso de spsite site = new spsite("http://localhost/mizuho")

} // método

[WebMethod]
público Proveedor[] GetVendorsOfType (cadena filterType)
{

cadena SpVendorSiteName; // Nombre del Real Sitio MOSS que aloja t
lista personalizada de proveedores.
cadena SpVendorListName; // Nombre de la actual lista de musgo proveedores.

SpVendorSiteName = ConfigurationSettings.AppSettings["VendorListHostingSite"].ToString();
SpVendorListName = ConfigurationSettings.AppSettings["VendorList"].ToString();

Proveedor[] resultList;
int vendorIndex = 0;
resultList = Nuevo Proveedor[1000];

// Inicializar la lista con un mensaje amigable por defecto.
Proveedor v = Nuevo Proveedor();
v.VendorName = "Seleccione un tipo de proveedor para completar esta lista.";
resultList[0] = v;

// Convertir el filtro inferior caso para más fácil comparación de cadenas más adelante.
filterType = filterType.ToLower();

// Si pasado el tipo de filtro es "prueba", generar algunos datos simples.
#región Tipo de filtro = "prueba de la"
Si (Iguales filterType.("prueba de"))
retorno GenerateTestVendors();
#endregion

Si (verdadero)
{
utilizando (SPSite sitio = Nuevo SPSite(SpVendorSiteName))
{
utilizando (SPWeb Web = página. OpenWeb())
{

v = NULL;

SPList currentList = web. Listas de[SpVendorListName];

// Recorrer en iteración todos los elementos de la lista de proveedores de.
foreach (SPItem vendorItem en currentList.Items)
{

cadena lowerVendorType;

lowerVendorType = vendorItem["PurchaseType"].ToString().ToLower();
lowerVendorType = lowerVendorType.Substring(3);

Si (igual a lowerVendorType.(filterType))
{
resultList[vendorIndex ] = Nuevo Proveedor(vendorItem);
}
} // Iterar a través de todos los proveedores en la lista


retorno TrimVendorArray(vendorIndex, resultList);
// volver resultList;

} // uso de spweb web = site.openweb()
} // uso de spsite site = new spsite("http://localhost/mizuho")

} // Si es cierto

retorno NULL;
}

privada Proveedor[] TrimVendorArray(int NewSize, Proveedor[] originalVendorArray)
{
Proveedor[] trimmedArray;

Si (NewSize == 0) NewSize = 1;
trimmedArray = Nuevo Proveedor[NewSize];

int currentCounter = 0;

para (currentCounter = 0; currentCounter < NewSize; currentCounter )
{
trimmedArray[currentCounter] = originalVendorArray[currentCounter];
}

retorno trimmedArray;

}
}

MOSS: Observaciones sobre la depuración de InfoPath

Mensajes de error de servidor de formulario de InfoPath son engañosos.

Durante el desarrollo de un formulario de InfoPath, Quisiera publicar a servidor MOSS y acceder al formulario de. La forma empezaría a cargar y luego generar un mensaje de error engañosa me hacia el registro de sucesos de windows para obtener más detalles. En realidad, ningún mensaje fue escrito para el registro de sucesos de windows. Prefiero, el mensaje fue enviado al registro de diagnóstico MOSS ascii. Puedes localizar a través de administración de servicios centrales.

Tienes que ser rápido en sus pies. MOSS le gusta escribir en el archivo de registro, con frecuencia y maximalismo. Esto puede ser recortada, pero el registro predeterminado escribiendo comportamiento es "todo lo más rápidamente posible".

MOSS: Actualizando una lista personalizada

Hay muchos buenos ejemplos de actualización de listas personalizadas mediante el SDK. Aquí está otro.

Problema del negocio: Formulario de InfoPath ha sido diseñada que permite a los usuarios entrar en línea requisiciones de compra. Requisición PO los números deben ser secuencia tradicional basado en valores enteros y calcula automáticamente.

Solución de negocio: Crear una lista personalizada de MOSS que contiene dos columnas: "ControlField" y "ControlValue". La columna valor contiene el siguiente número de requisición de compra. Tenga en cuenta que el genérico "control" Convención de nomenclatura proporciona para campos de control futuros que pueden utilizarse como sea necesario.

Solución técnica: Crear un servicio web accedido por el cliente de InfoPath. El servicio web vuelta devuelve el siguiente número de requisición de compra y actualiza el valor de la lista.

Lecciones aprendidas:

  • Al agregar este servicio web como origen de datos en el formulario de InfoPath, Me pareció necesario para convertirlo en un udc y almacenarlo en una biblioteca de conexiones de datos.
  • También me pareció necesario para permitir el dominio cruzado de secuencias de comandos mediante la administración de servicios centrales // Administración de aplicaciones // configuración del servidor de forma.
  • La primera vez la forma trató de acceso al servicio web, Toma un tiempo y en ocasiones, sería tiempo. Ha jugueteado con los ajustes de configuración del servidor de forma para ampliar las opciones de tiempo de espera y que parecía ayudar a.

El código:

utilizando Sistema;
utilizando System.Web;
utilizando System.Web.Services;
utilizando System.Web.Services.Protocols;
utilizando Microsoft.SharePoint;
utilizando System.Configuration;

[WebService(Namespace = "http://www.conchango.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
público clase PoService : System.Web.Services.WebService
{
público PoService () {

//Descomentar la siguiente línea si utiliza componentes diseñados
//InitializeComponent();
}

/// <Resumen>
/// Obtener el número siguiente de la lista de control número de sharepoint po.
/// Incrementar el número de la lista.
/// </Resumen>
/// <Devuelve></Devuelve>
[WebMethod]
público cadena GetNextPoNumber()
{
cadena SpPoControlSiteName; // Nombre del Real Sitio MOSS que aloja la lista de Control de la PO.
cadena SpPoControlListName; // Nombre de la lista de musgo real que contiene el control de la Po.

SpPoControlSiteName = ConfigurationSettings.AppSettings["PoControlListHostingSite"].ToString();
SpPoControlListName = ConfigurationSettings.AppSettings["PoControlList"].ToString();

cadena nextPoReqNumber = "xyzzy";

utilizando (SPSite sitio = Nuevo SPSite(SpPoControlSiteName))
{
utilizando (SPWeb Web = página. OpenWeb())
{

SPList currentList = web. Listas de[SpPoControlListName];

foreach (SPItem controlItem en currentList.Items)
{

Si (((cadena)controlItem["ControlField"]).Es igual a("NextPoNumber"))
{
nextPoReqNumber = (cadena)controlItem["ControlValue"];

int int_nextPoReqNumber;
int_nextPoReqNumber = Convertir.ToInt32(nextPoReqNumber);

int_nextPoReqNumber ;

controlItem["ControlValue"] = int_nextPoReqNumber;
controlItem.Update();
}

} // Localización de, lectura y actualización del número en la lista.


} // uso de spweb web = site.openweb()
} // uso de spsite site = new spsite("http://localhost/mizuho")

retorno nextPoReqNumber;

}
}