MOSS / Servidor de formes d'InfoPath (L'InfoPath 2007) actuació de llista desplegable

Categoria addicional: L'InfoPath

Resum: Un InfoPath 2007 forma desplegada a un servidor de molsa proporciona una llista desplegable de venedors lligat a una llista personalitzada de molsa. En seleccionar un proveïdor, regles assignar valors de camp a un grapat de camps de text com ara el nom de representant de vendes, Adreça, ciutat, estat, postal i telèfon. Rendiment és horrible. Ens adonem que rendiment empitjora (d'una manera no lineal) per a cada àmbit addicional podem actualitzar aquesta manera. És a dir, Si ens acaba d'actualitzar el nom representant de vendes, triga [x] quantitat de temps. Si actualitzem representant de vendes, address1, address2, ciutat, estat, cremallera, triga 10 vegades més.

Solució: Escriure un servei web (es poden trobar exemples de codi aquí) que es transmet en nom d'un proveïdor i torna altra vegada les dades de venedor. Llavors, assignar els camps d'aquesta manera. Encara que això sembla massa lent, hi va haver cap diferència posades en el rendiment quan podem assignada 1 camp enfront 8 camps. Com una gratificació afegida, els usuaris aconseguir un fresc "contactant amb el servidor" Cylon efecte mentre esperen per al formulari invocar i consumir els resultats del servei.

MOSS: S'ha produït una excepció. (Excepció de HRESULT: 0x 80020009 (DISP_E_EXCEPTION))

ACTUALITZACIÓ: Ens mai determinaren que la causa d'arrel d'aquest problema i mai superfície una altra vegada.

Notem que de sobte durant la implementació d'un lloc de desenvolupament, dos usuaris són incapaços d'accedir a una col·lecció de llocs. Els comptes poden autenticar al lloc principal, però quan es tracta d'accedir a una col·lecció particular, només aconsegueixen una pantalla en blanc. No hi ha errors que es Mostra, només una pàgina blanca en blanc.

Podem entrar com un col. lecció de lloc admin i proveu d'afegir un d'aquells usuaris com un administrador del lloc i aquesta vegada, en prémer "OK", arribem a aquest missatge:

S'ha produït una excepció. (Excepció de HRESULT: 0x 80020009 (DISP_E_EXCEPTION))

Vam passar algun temps a investigar això i per desgràcia, no va arribar a res útil. Hi havia alguns missatges en el registre de diagnòstic, però era difícil exactament relacionar-los amb aquest assumpte.

Al final, hem de suprimir la col·lecció de llocs i tornar-lo i que resolt.

Si puc esbrinar què provocava això en el futur, Vaig a actualitzar aquest post.

MOSS: Itereu a través de llistes de costum i tornar les dades filtrades al InfoPath

Escenari de negocis:

Proporcionar un mètode que permet als usuaris introduir precisa compra requisitions ràpidament.

Problema de negoci:

El client fa negoci amb diversos centenars de proveïdors.

Els venedors són "tipus" específics. Això significa que un distribuïdor ven equips informàtics (e. g. Dell) o material d'oficina (e. g. Staples).

Com podem permetre als usuaris finals que creen compra requisitions seleccionar un proveïdor vàlid?

Solució de negoci:

Diferenciar els venedors en el sistema via "tipus".

Permeten usuaris seleccionar el tipus de"" de producte and then provide un conjunt filtrat de venedors apropiats.

Solució tècnica:

Una forma d'InfoPath ha estat dissenyat que permet als usuaris introduir en línia compra requisitions.

Selecció de venedor de control de dues llistes de selecció d'InfoPath. Primer, l'usuari selecciona un tipus de"compra". Això limita una segona llista de selecció per contenir només els venedors que venen per a aquest tipus de compra. Aquest és un clàssic en cascada desplegable.

Els venedors s'emmagatzemen en una llista personalitzada de MOSS amb la columnes personalitzat per atributs venedor com ara nom, Adreça i especialment "tipus".

Implementar un servei web per a un client de l'InfoPath consumir que itera a través de la llista de proveïdors de costum, tornar només els venedors que coincideixen amb un subministrada "tipus".

Invocar el servei web mitjançant el formulari de l'InfoPath.

Lliçons apreses:

  • Primer, sembla necessari per seguir aquest camí. Hauria preferit de fer la filtració totalment dins de l'InfoPath i no crear cap funcionalitat servei web aquí. No obstant això, servidor de formes no proporciona la capacitat de filtració requerida. Podem posar una regla a del tipus"" Llista de selecció en forma per tipus de tornar a obrir la consulta proveïdors, però no podem aconseguir-lo treballar pròpiament. Per tant, era necessari implementar el servei de web.
  • Aquest és un clàssic "cascada llista de selecció" problema a l'InfoPath formes món del servidor i hi ha molts bons exemples fora d'allà que expliquen com resoldre-ho.
  • Un valor en blanc per a una columna a la llista de proveïdors no retorna una cadena buida quan es fa referència com aquest: initItem["El nom del proveïdor"]. En canvi, es retorna un valor null.

Alguns altres Notes:

  • Puc retornar una matriu[] dels venedors perquè he tingut algunes dificultats tornant un ArrayList. L'InfoPath es queixava sobre això i no tinc el temps o la inclinació de lluitar pel. Això, clar, posa un límit artificial sobre el nombre total de venedors. Això també em d'aplicar una retallada obligat() mètode en la matriu perquè m'agrada la idea de tornar enrere 100 dels venedors nuls. L'InfoPath no li importa, però li molestava en mi. (Una altra vegada, això era més fàcil que l'InfoPath barallant perquè el ArrayLists).
  • Vaig implementar un GetSpecificVendorByName() funció, així, que pot ser instructiu.

El codi:

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

/// <resum>
///
Proveïdor de servei: Proporciona venedor relacionats amb serveis que avui són consumides per una forma de client de l'infopath.
///
/// Història:
/// ——–
/// 07/24/07: Inicial de codificació, Paul J. Gavin de Conchango.
///
/// </resum>
[WebService(Namespace = "http://www.conchango.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
públic classe VendorService : System.Web.Services.WebService
{

/// <resum>
/// Representa un venedor d'una llista de costum sharepoint mantingut per MSUSA.
/// </resum>
públic classe Venedor
{
públic Venedor() { }

públic Venedor(SPItem initItem)
{
Si (! (initItem["El nom del proveïdor"] == nul·la)) VendorName = initItem["El nom del proveïdor"].ToString();
Si (! (initItem[«Discurs 1"] == nul·la)) VendorAddress1 = initItem[«Discurs 1"].ToString();
Si (! (initItem[«Discurs 2"] == nul·la)) VendorAddress2 = initItem[«Discurs 2"].ToString();
Si (! (initItem["Ciutat"] == nul·la)) VendorCity = initItem["Ciutat"].ToString();
Si (! (initItem["VendorPhone"] == nul·la)) VendorPhone = initItem["VendorPhone"].ToString();
Si (! (initItem["PurchaseType"] == nul·la)) VendorType = initItem["PurchaseType"].ToString();
Si (! (initItem["L'estat"] == nul·la)) VendorState = initItem["L'estat"].ToString();
Si (! (initItem["Zip"] == nul·la)) VendorZip = initItem["Zip"].ToString();
Si (!(initItem["Fax"] == nul·la)) VendorFax = initItem["Fax"].ToString();
Si (!(initItem["SalesRepName"] == nul·la)) VendorSalesRepName = initItem["SalesRepName"].ToString();

VendorItemId = initItem.ID; // ID únic mantingut mitjançant molsa.
}

públic Int VendorItemId;
públic corda VendorName;
públic corda VendorAddress1;
públic corda VendorAddress2;
públic corda VendorCity;
públic corda VendorState;
públic corda VendorZip;
públic corda VendorPhone;
públic corda VendorType;
públic corda VendorSalesRepName;
públic corda VendorFax;
}

públic VendorService () {

//Incomenti la línia següent si utilitzant dissenyat components de
//InitializeComponent();
}

privat Venedor[] GenerateTestVendors()
{
Venedor[] resultList;
resultList = nou Venedor[100];

Venedor v;
v = nou Venedor();
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 = nou Venedor();

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 = nou Venedor();
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;

retorn resultList;

}

[WebMethod]
públic Venedor GetSpecificVendorById(Int vendorId)
{
corda SpVendorSiteName; // Nom del lloc real molsa que allotja la llista personalitzades proveïdor.
corda SpVendorListName; // Nom de la llista actual de molsa que conté venedors.

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

utilitzant (SPSite lloc = nou SPSite(SpVendorSiteName))
{

utilitzant (SPWeb web = lloc. OpenWeb())
{

SPList currentList = la web. Llistes[SpVendorListName];

SPItem specificItem = currentList.Items[vendorId];

retorn nou Venedor(specificItem);

} // utilitzant spweb web = site.openweb()
} // utilitzant spsite lloc = spsite nou("http://localhost/mizuho")

}

[WebMethod]
// Assumeix que el nom de proveïdor és únic, des de la perspectiva empresarial
públic Venedor GetSpecificVendorByVendorName(corda ser)
{
corda SpVendorSiteName; // Nom del lloc real molsa que allotja la llista personalitzades proveïdor.
corda SpVendorListName; // Nom de la llista actual de molsa que conté venedors.

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

utilitzant (SPSite lloc = nou SPSite(SpVendorSiteName))
{
utilitzant (SPWeb web = lloc. OpenWeb())
{

SPList currentList = la web. Llistes[SpVendorListName];

foreach (SPItem vendorItem en currentList.Items)
{
Si (vendorItem["El nom del proveïdor"] == nul·la) «««;

Si (vendorItem["El nom del proveïdor"].ToString().És igual a(ser))
retorn nou Venedor(vendorItem);
}

Venedor v = nou Venedor();
v.VendorPhone = "no es troba: " + ser;

retorn v;

retorn nul·la;

} // utilitzant spweb web = site.openweb()
} // utilitzant spsite lloc = spsite nou("http://localhost/mizuho")

} // mètode

[WebMethod]
públic Venedor[] GetVendorsOfType (corda filterType)
{

corda SpVendorSiteName; // Nom del lloc real molsa que allotja t
llista personalitzades de proveïdors de va.
corda SpVendorListName; // Nom de la llista actual de molsa que conté venedors.

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

Venedor[] resultList;
Int vendorIndex = 0;
resultList = nou Venedor[1000];

// Inicialitzar la llista amb un missatge amable per defecte.
Venedor v = nou Venedor();
v.VendorName = "Seleccionar un tipus de venedor a poblar aquesta llista.";
resultList[0] = v;

// Convertir el filtre a minúscules per a la comparació de corda més fàcil més tard.
filterType = filterType.ToLower();

// Si el tipus de filtre passat és "prova", generar algunes dades simples.
#regió Tipus de filtre = "prova"
Si (equival a filterType.(«prova"))
retorn GenerateTestVendors();
#endregion

Si (True)
{
utilitzant (SPSite lloc = nou SPSite(SpVendorSiteName))
{
utilitzant (SPWeb web = lloc. OpenWeb())
{

v = nul·la;

SPList currentList = la web. Llistes[SpVendorListName];

// Recórrer tots els elements a la llista de proveïdors.
foreach (SPItem vendorItem en currentList.Items)
{

corda lowerVendorType;

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

Si (equival a lowerVendorType.(filterType))
{
resultList[vendorIndex ] = nou Venedor(vendorItem);
}
} // itereu seguit tots els proveïdors de la llista


retorn TrimVendorArray(vendorIndex, resultList);
// tornar resultList;

} // utilitzant spweb web = site.openweb()
} // utilitzant spsite lloc = spsite nou("http://localhost/mizuho")

} // Si és cert

retorn nul·la;
}

privat Venedor[] TrimVendorArray(Int newsize, Venedor[] originalVendorArray)
{
Venedor[] trimmedArray;

Si (newsize = = 0) newsize = 1;
trimmedArray = nou Venedor[newsize];

Int currentCounter = 0;

per a (currentCounter = 0; currentCounter < newsize; currentCounter )
{
trimmedArray[currentCounter] = originalVendorArray[currentCounter];
}

retorn trimmedArray;

}
}

MOSS: Observacions sobre depuració d'InfoPath

Missatges d'error de servidor de formulari de l'InfoPath són enganyoses.

Durant el desenvolupament d'un formulari InfoPath, Anava a enviar-lo al servidor de molsa i accedir al mòdul de. La forma començaria carregar i després generar un missatge d'error enganyosa adreçar-me al registre d'esdeveniments de windows per a més detalls. De fet, va ser escrita cap missatge d'incidències del windows. Més aviat, el missatge va ser enviat al registre diagnòstic molsa ascii. Es que poden rastrejar mitjançant l'administració de serveis centrals.

Has de ser ràpid en els peus. MOLSA li agrada escriure al fitxer de registre, freqüentment i donant informació. Això pot ser ajustat però el registre per defecte escriptura comportament és "tot el més aviat possible".

MOSS: Actualitzar una llista personalitzada

Hi ha molts bons exemples d'actualització de les llistes personalitzades mitjançant l'SDK. Aquí és un altre.

Problema de negoci: Formulari InfoPath ha estat dissenyat que permet als usuaris introduir en línia compra requisitions. PO sol·licitud ha de ser números de seqüència tradicional basat en valors enters i calcula automàticament.

Solució de negoci: Crear una llista personalitzada de molsa que contenen dues columnes: "ControlField" i "ControlValue". La columna de valor conté el següent número de sol·licitud de compra. Tingueu en compte que el genèric "control" proporciona Convenció de nomenclatura per als camps de futur control que es pot utilitzar com sigui necessari.

Solució tècnica: Crear un servei web accessible per part del client de l'InfoPath. El servei web torna altra vegada el proper número de la sol·licitud compra i actualitza el valor de la llista.

Lliçons apreses:

  • Quan afegiu aquest servei web com a font de dades al formulari de l'InfoPath, Em va semblar necessari per convertir-lo en un udc i emmagatzemar-lo en una biblioteca de connexió de dades.
  • Jo també resultava necessari habilitar els scripts entre dominis mitjançant l'administració de serveis centrals // aplicacions de gestió // configuració de servidor de forma.
  • La primera vegada provat el formulari accedir al servei web, pren un temps i d'ocasió, ho faria temps d'espera. Em fiddled amb escenes de configuració de servidor de forma d'ampliar la configuració del temps d'espera i que semblava que ajudés.

El codi:

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

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

//Incomenti la línia següent si utilitzant dissenyat components de
//InitializeComponent();
}

/// <resum>
/// Obtenir el següent nombre PO de la llista del sharepoint po nombre control.
/// Incrementar el nombre de PO en aquesta llista.
/// </resum>
/// <devolucions></devolucions>
[WebMethod]
públic corda GetNextPoNumber()
{
corda SpPoControlSiteName; // Nom del lloc real molsa que allotja la llista de PO Control.
corda SpPoControlListName; // Nom de la llista actual de molsa que contenen el control Po.

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

corda nextPoReqNumber = "xyzzy";

utilitzant (SPSite lloc = nou SPSite(SpPoControlSiteName))
{
utilitzant (SPWeb web = lloc. OpenWeb())
{

SPList currentList = la web. Llistes[SpPoControlListName];

foreach (SPItem controlItem en currentList.Items)
{

Si (((corda)controlItem["ControlField"]).És igual a("NextPoNumber"))
{
nextPoReqNumber = (corda)controlItem["ControlValue"];

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

int_nextPoReqNumber ;

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

} // Localització, llegir i actualitzar el nombre PO a la llista.


} // utilitzant spweb web = site.openweb()
} // utilitzant spsite lloc = spsite nou("http://localhost/mizuho")

retorn nextPoReqNumber;

}
}