MOUSSE / InfoPath Forms Server (InfoPath 2007) performance dans la liste déroulante

Catégorie supplémentaire: InfoPath

Résumé: Un InfoPath 2007 formulaire déployé sur un serveur MOSS fournit une liste déroulante des vendeurs liée à une liste personnalisée de MOSS. Lorsque vous sélectionnez un fournisseur, règles assigner des valeurs de champ à une poignée de champs de texte tels que le nom de représentant des ventes, adresse, ville, État, zip et téléphone. Performance est horrible. Nous remarquons que la performance s'aggrave (dans un mode non linéaire) pour chaque champ supplémentaire, nous mettons à jour cette façon. C'est-à-dire, Si nous avons juste mettre à jour le nom de représentant des ventes, Il faut [x] laps de temps. Si nous mettons à jour représentant des ventes, adresse1, adresse2, ville, État, zip, Il faut 10 fois plus longtemps.

Solution: Écrire un service web (exemple de code se trouvent ici) qui est passé au nom de la vendeuse et elle retourne retour les détails du vendeur. Puis, assigner les champs de cette manière. Même si cela semble trop lente, Il n'y n'avait aucun différence perceptible dans les performances lorsque nous avons attribué 1 champ versus 8 champs. En prime, les utilisateurs obtiennent une cool "communiquant avec le serveur" Cylon effet pendant qu'ils attendent pour le formulaire d'invoquer et de consommer le service résultats.

MOUSSE: Exception s'est produite. (Exception de HRESULT: 0x 80020009 (DISP_E_EXCEPTION))

MISE À JOUR: Nous avons déterminé jamais la cause de ce problème et il jamais surface encore une fois.

Nous remarquons que soudainement au cours de la mise en oeuvre d'un site de développement, deux utilisateurs ne peuvent accéder à une collection de sites. Ces comptes peuvent s'authentifier sur le site principal, mais lorsque vous essayez d'accéder à une collection de sites particulière, avoir juste un écran vide. Aucune erreur ne s'affichée, juste une page blanche vierge.

Nous connecter en tant qu'un administrateur de collection de site et essayez d'ajouter un de ces utilisateurs comme un administrateur de site et cette fois, à appuyer sur « OK », Nous obtenons ce message:

Exception s'est produite. (Exception de HRESULT: 0x 80020009 (DISP_E_EXCEPTION))

Nous avons passé quelques temps cette recherche et malheureusement, n'aboutir à rien d'utile. Il y a certains messages dans le journal de diagnostic, mais il était difficile de les corréler exactement cette question.

En fin de compte, Nous avons supprimer de la collection de sites et recréé et qu'il résolu.

Si je figure ce que cela causé dans l'avenir, Je vais mettre à jour ce post.

MOUSSE: Itération sur les listes personnalisées et retourner des données filtrées à InfoPath

Scénario d'entreprise:

Fournir une méthode qui permet aux utilisateurs d'entrer rapidement les demandes d'achat précis.

Problème commercial:

Le client fait affaire avec plusieurs fournisseurs de centaines.

Les fournisseurs sont de type"" spécifiques. Cela signifie qu'un vendeur vend du matériel de l'ordinateur (e.g. Référence Dell) ou de fournitures de bureau (e.g. Staples).

Comment est-ce que nous avons active des utilisateurs finaux qui créer achat réquisitions, sélectionnez un fournisseur valide?

Solution d'affaires:

Différencier les vendeurs dans le système par l'intermédiaire de « type ».

Permettre aux utilisateurs de sélectionner le type"" du produit et ensuite fournir un ensemble filtré de fournisseurs appropriés.

Solution technique:

Un formulaire InfoPath a été conçu pour que les demandes d'achat permet aux utilisateurs de s'inscrire en ligne.

Deux listes de sélection InfoPath contrôlent la sélection des fournisseurs. Première, l'utilisateur sélectionne un type de « achat ». Ce qui limite une deuxième liste de sélection afin qu'il contienne uniquement les fournisseurs qui vendent pour ce type d'achat. Il s'agit d'un classique déroulantes en cascade.

Vendeurs sont stockés dans une liste personnalisée de mousse avec des colonnes personnalisées pour les attributs du vendeur comme nom, adresse et surtout « type ».

Implémenter un service web pour un client InfoPath à consommer qui parcourt la liste des fournisseurs personnalisés, retourner uniquement les fournisseurs correspondant à un « type » fourni.

Invoquer le service web via le formulaire InfoPath.

Leçons apprises:

  • Première, Il semble nécessaire d'emprunter cette voie. J'aurais préféré faire le filtrage entièrement dans InfoPath et ne crée pas une fonctionnalité du service web ici. Cependant, serveur de formulaires ne fournit pas la fonctionnalité de filtrage requise. Nous pouvons mettre une règle sur un "type" liste de sélection dans le formulaire de sorte de ré-ouvrir la requête du vendeur, mais nous ne pouvons pas faire fonctionner correctement. Donc, il était nécessaire de mettre en place le service web.
  • Il s'agit d'une liste de sélection en cascade classique"" problème dans l'InfoPath forme monde serveur et il y a là-bas plusieurs bons exemples qui expliquent comment résoudre ce problème.
  • Une valeur vide pour une colonne dans la liste des fournisseurs ne retourne pas une chaîne vide lorsqu'ils sont référencés comme ceci: initItem["Nom du vendeur"]. Au lieu de cela, elle retourne une valeur null.

Quelques autres Notes:

  • Je reviens d'un tableau[] des vendeurs parce que j'ai eu quelques difficultés à retourner un ArrayList. InfoPath a été se plaindre à ce sujet et je n'avais pas le temps ou l'envie de se battre pour elle. Ce, Bien sûr, met une limite artificielle sur le nombre total de fournisseurs. Il contraint également moi pour mettre en œuvre une garniture() méthode sur le tableau parce que je déteste l'idée d'un retour en arrière 100 de vendeurs null. InfoPath ne se soucie pas, mais il a harcelé à moi. (Encore une fois, C'était plus facile que disputent InfoPath ArrayLists).
  • J'ai implémenté un GetSpecificVendorByName() fonction aussi bien, qui peut être instructif.

Le code:

à l'aide de Système;
à l'aide de System.Web;
à l'aide de System.Web.Services;
à l'aide de System.Web.Services.Protocols;
à l'aide de Microsoft.SharePoint;
à l'aide de System.Configuration;

/// <Résumé>
///
Fournisseur Service: Offre des services de fournisseurs associés qui aujourd'hui sont consommés par un formulaire du client infopath.
///
/// Histoire:
/// ——–
/// 07/24/07: Codage initial, J Paul. Gavin de Conchango.
///
/// </Résumé>
[WebService(Namespace = « http://www.Conchango.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public classe VendorService : System.Web.Services.WebService
{

/// <Résumé>
/// Représente un fournisseur d'une liste sharepoint personnalisée maintenu par Berthon.
/// </Résumé>
public classe Fournisseur
{
public Fournisseur() { }

public Fournisseur(SPItem initItem)
{
Si (! (initItem["Nom du vendeur"] == null)) VendorName = initItem["Nom du vendeur"].ToString();
Si (! (initItem["Adresse 1"] == null)) VendorAddress1 = initItem["Adresse 1"].ToString();
Si (! (initItem["Adresse 2"] == null)) VendorAddress2 = initItem["Adresse 2"].ToString();
Si (! (initItem["City"] == null)) VendorCity = initItem["City"].ToString();
Si (! (initItem["VendorPhone"] == null)) VendorPhone = initItem["VendorPhone"].ToString();
Si (! (initItem["PurchaseType"] == null)) VendorType = initItem["PurchaseType"].ToString();
Si (! (initItem["État"] == null)) VendorState = initItem["État"].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 unique maintenue par l'intermédiaire de mousse.
}

public int VendorItemId;
public chaîne VendorName;
public chaîne VendorAddress1;
public chaîne VendorAddress2;
public chaîne VendorCity;
public chaîne VendorState;
public chaîne VendorZip;
public chaîne VendorPhone;
public chaîne VendorType;
public chaîne VendorSalesRepName;
public chaîne VendorFax;
}

public VendorService () {

//Décommentez la ligne suivante si vous utilisez des composants conçus
//InitializeComponent();
}

privé Fournisseur[] GenerateTestVendors()
{
Fournisseur[] resultList;
resultList = Nouveau Fournisseur[100];

Fournisseur v;
v = Nouveau Fournisseur();
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 = Nouveau Fournisseur();

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 = Nouveau Fournisseur();
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;

retour resultList;

}

[WebMethod]
public Fournisseur GetSpecificVendorById(int VendorID)
{
chaîne SpVendorSiteName; // Nom du site MOSS réel qui héberge la liste personnalisée du vendeur.
chaîne SpVendorListName; // Nom de la liste réelle de mousses contenant des vendeurs.

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

à l'aide de (SPSite site = Nouveau SPSite(SpVendorSiteName))
{

à l'aide de (SPWeb Web = site. OpenWeb())
{

SPList currentList = web. Listes[SpVendorListName];

SPItem specificItem = currentList.Items[VendorID];

retour Nouveau Fournisseur(specificItem);

} // Using web As spweb = site.openweb()
} // en utilisant spsite site = nouvelle spsite(« http://localhost/mizuho")

}

[WebMethod]
// Suppose que le nom du vendeur est unique, dans une perspective d'affaires
public Fournisseur GetSpecificVendorByVendorName(chaîne être)
{
chaîne SpVendorSiteName; // Nom du site MOSS réel qui héberge la liste personnalisée du vendeur.
chaîne SpVendorListName; // Nom de la liste réelle de mousses contenant des vendeurs.

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

à l'aide de (SPSite site = Nouveau SPSite(SpVendorSiteName))
{
à l'aide de (SPWeb Web = site. OpenWeb())
{

SPList currentList = web. Listes[SpVendorListName];

foreach (SPItem vendorItem dans currentList.Items)
{
Si (vendorItem["Nom du vendeur"] == null) continuer;

Si (vendorItem["Nom du vendeur"].ToString().Est égal à(être))
retour Nouveau Fournisseur(vendorItem);
}

Fournisseur v = Nouveau Fournisseur();
v.VendorPhone = "non trouvé: " + être;

retour v;

retour null;

} // Using web As spweb = site.openweb()
} // en utilisant spsite site = nouvelle spsite(« http://localhost/mizuho")

} // méthode

[WebMethod]
public Fournisseur[] GetVendorsOfType (chaîne filterType)
{

chaîne SpVendorSiteName; // Nom du site MOSS réel qui héberge t
liste personnalisée de HE du vendeur.
chaîne SpVendorListName; // Nom de la liste réelle de mousses contenant des vendeurs.

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

Fournisseur[] resultList;
int vendorIndex = 0;
resultList = Nouveau Fournisseur[1000];

// Initialiser la liste avec un message amical par défaut.
Fournisseur v = Nouveau Fournisseur();
v.VendorName = « Sélectionner un type de fournisseur pour remplir cette liste.";
resultList[0] = v;

// Convertir le filtre en minuscules pour faciliter la comparaison string plus tard.
filterType = filterType.ToLower();

// Si le type de filtre passé est « test », générer des données simples.
#région Type de filtre = "test"
Si (Equals filterType.(« test"))
retour GenerateTestVendors();
#endregion

Si (True)
{
à l'aide de (SPSite site = Nouveau SPSite(SpVendorSiteName))
{
à l'aide de (SPWeb Web = site. OpenWeb())
{

v = null;

SPList currentList = web. Listes[SpVendorListName];

// Parcourir tous les éléments dans la liste des fournisseurs.
foreach (SPItem vendorItem dans currentList.Items)
{

chaîne lowerVendorType;

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

Si (égal à lowerVendorType.(filterType))
{
resultList[vendorIndex ] = Nouveau Fournisseur(vendorItem);
}
} // une itération à travers tous les vendeurs dans la liste


retour TrimVendorArray(vendorIndex, resultList);
// retour resultList;

} // Using web As spweb = site.openweb()
} // en utilisant spsite site = nouvelle spsite(« http://localhost/mizuho")

} // Si elle est vraie

retour null;
}

privé Fournisseur[] TrimVendorArray(int newSize, Fournisseur[] originalVendorArray)
{
Fournisseur[] trimmedArray;

Si (newSize == 0) newSize = 1;
trimmedArray = Nouveau Fournisseur[newSize];

int currentCounter = 0;

pour (currentCounter = 0; currentCounter < newSize; currentCounter )
{
trimmedArray[currentCounter] = originalVendorArray[currentCounter];
}

retour trimmedArray;

}
}

MOUSSE: Observations sur le débogage d'InfoPath

Messages d'erreur du serveur formulaire InfoPath sont trompeurs.

Au cours du développement d'un formulaire InfoPath, Je poste serveur MOSS et accéder au formulaire. Le formulaire pour commencer à charger et générer ensuite un message d'erreur trompeuse me pointant vers le journal des événements windows pour plus de détails. En fait, aucun message n'a été écrit dans le journal des événements windows. Plutôt, le message a été envoyé pour le journal de diagnostic de MOSS ascii. Vous pouvez suivre que vers le bas par l'intermédiaire de l'administration centrale services.

Vous devez être rapide sur vos pieds. MOSS aime à écrire dans le fichier journal, fréquemment et détails. Cela peut être coupé, mais le comportement d'écriture de journal par défaut est "tout aussi rapidement que possible".

MOUSSE: Mise à jour d'une liste personnalisée

Il y a beaucoup de bons exemples de mise à jour de listes personnalisées via le SDK. Voici encore un autre.

Problème commercial: Formulaire InfoPath a été conçu pour que les demandes d'achat permet aux utilisateurs de s'inscrire en ligne. Réquisition de PO numéros devraient être séquence traditionnelle basée à valeurs entières et calculé automatiquement.

Solution d'affaires: Créer une liste personnalisée de mousse contenant deux colonnes: "ControlField" et « ControlValue ». La colonne valeur contient le prochain numéro de demande d'achat. Notez que le générique "contrôle" convention de nommage fournit pour les champs de contrôle futur qui peuvent être utilisés selon les besoins.

Solution technique: Créer un service web accédé par le client InfoPath. Le service web retourne en arrière le prochain numéro de réquisition d'achat et met à jour la valeur de la liste.

Leçons apprises:

  • Lors de l'ajout de ce service web comme une source de données au formulaire InfoPath, J'ai jugé nécessaire de convertir en une udc et la stocker dans une bibliothèque de connexions de données.
  • Je l'ai trouvé aussi nécessaire pour activer le script inter-domaines via l'administration centrale services // gestion des applications // configuration de serveur de formulaire.
  • La première fois la forme a essayé d'accéder au service web, Il faut du temps et à l'occasion, Il serait temps. J'ai bidouillé avec les paramètres de configuration de serveur de formulaire d'élargir les paramètres de délai d'attente et qui semblent aider.

Le code:

à l'aide de Système;
à l'aide de System.Web;
à l'aide de System.Web.Services;
à l'aide de System.Web.Services.Protocols;
à l'aide de Microsoft.SharePoint;
à l'aide de System.Configuration;

[WebService(Namespace = « http://www.Conchango.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public classe PoService : System.Web.Services.WebService
{
public PoService () {

//Décommentez la ligne suivante si vous utilisez des composants conçus
//InitializeComponent();
}

/// <Résumé>
/// Obtenir le numéro suivant dans la liste numéro de contrôle sharepoint po.
/// Incrémenter le numéro de PO dans cette liste.
/// </Résumé>
/// <retourne></retourne>
[WebMethod]
public chaîne GetNextPoNumber()
{
chaîne SpPoControlSiteName; // Nom du site MOSS réel qui héberge la liste de contrôle de PO.
chaîne SpPoControlListName; // Nom de la liste réelle de MOSS qui contient le contrôle de Po.

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

chaîne nextPoReqNumber = "xyzzy";

à l'aide de (SPSite site = Nouveau SPSite(SpPoControlSiteName))
{
à l'aide de (SPWeb Web = site. OpenWeb())
{

SPList currentList = web. Listes[SpPoControlListName];

foreach (SPItem controlItem dans currentList.Items)
{

Si (((chaîne)controlItem["ControlField"]).Est égal à("NextPoNumber"))
{
nextPoReqNumber = (chaîne)controlItem["ControlValue"];

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

int_nextPoReqNumber ;

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

} // Localisation, lire et mettre à jour le nombre de PO dans la liste.


} // Using web As spweb = site.openweb()
} // en utilisant spsite site = nouvelle spsite(« http://localhost/mizuho")

retour nextPoReqNumber;

}
}