כוידעשלעך אַרטשיוועס: יולי 2007

מאָך: יטעראַטינג דורך מנהג רשימות און אומגעקערט געפילטערט דאַטן צו ינפאָפּאַטה

ביזנעס סינעריאָו:

צושטעלן אַ אופֿן אַז ינייבאַלז ניצערס צו אַרייַן פּינטלעך קויפן רעקוויסיטיאָנס געשווינד.

ביזנעס פּראָבלעם:

דער קליענט טוט געשעפט מיט עטלעכע הונדערט ווענדאָרס.

Vendors are "type" ספּעציפיש. דאס מיטל אַז אַ פאַרקויפער פארקויפט קאָמפּיוטער עקוויפּמענט (e.g. דעל) אָדער אָפיס סופּפּליעס (e.g. סטייפּאַלז).

How do we enable end users who create purchase requisitions select a valid vendor?

ביזנעס סאַלושאַן:

Differentiate vendors in the system via "type".

Enable users to select the "type" of product and then provide a filtered set of appropriate vendors.

טעכניש סאַלושאַן:

An InfoPath form has been designed that enables users to enter online purchase requisitions.

Two InfoPath selection lists control vendor selection. ערשטער, the user selects a "purchase type". This limits a second selection list to contain only vendors that sell for that purchase type. This is a classic cascading drop-down.

Vendors are stored in a MOSS custom list with custom columns for vendor attributes such as name, address and especially "type".

Implement a web service for an InfoPath client to consume that iterates through the custom vendor list, returning only vendors matching a supplied "type".

Invoke the web service via the InfoPath form.

Lessons Learned:

  • ערשטער, it seems necessary to go this route. I would have preferred to do the filtering entirely within InfoPath and not create any web service functionality here. אָבער, forms server does not provide the required filtering capability. We can put a rule onto a the "type" selection list in the form to sort of re-open the vendor query, but we can’t get it to work properly. דעריבער, it was necessary to implement the web service.
  • This is a classic "cascading selection list" פּראָבלעם אין די ינפאָפּאַטה פארמען סערווירער וועלט און עס זענען פילע גוט ביישפילן אויס דאָרט אַז דערקלערן ווי צו סאָלווע דעם.
  • א פּוסט ווערט פֿאַר אַ זייַל אין דער פאַרקויפער רשימה טוט ניט צוריקקומען אַן ליידיק שטריקל ווען רעפראַנסט ווי דעם: יניטיטעם["Vendor Name"]. אַנשטאָט, עס קערט אַ נאַל.

עטלעכע אנדערע נאָטעס:

  • איך צוריקקומען אַ מענגע[] פון ווענדאָרס ווייַל איך האט עטלעכע שוועריקייט אומגעקערט אַ אַררייַליסט. ינפאָפּאַטה איז קאַמפּליינינג וועגן אים און איך האט נישט האָבן די צייַט אָדער דער יצר צו קעמפן איבער אים. דעם, אַוואַדע, שטעלט אַ קינסטלעך שיעור אויף די גאַנץ נומער פון ווענדאָרס. עס אויך געצוואונגען מיר צו ינסטרומענט אַ טרים() method on the array because I hate the idea of returning back 100’s of null vendors. ינפאָפּאַטה טוט ניט זאָרגן, אָבער עס נאַגד בייַ מיר. (ווידער, דאָס איז געווען גרינגער ווי פייטינג ינפאָפּאַטה איבער אַררייַליסץ).
  • איך ימפּלאַמענאַד אַ געצפּעסיפיקווענדאָרבינאַמע() פונקציאָנירן ווי געזונט, וואָס קען זייַן ינסטראַקטיוו.

די קאָד:

ניצן סיסטעם;
ניצן System.Web;
ניצן System.Web.Services;
ניצן System.Web.Services.Protocols;
ניצן Microsoft.SharePoint;
ניצן System.Configuration;

/// <קיצער>
///
Vendor Service: Provides vendor related services which today are consumed by an infopath client form.
///
/// History:
/// ——–
/// 07/24/07: Initial coding, Paul J. Gavin of Conchango.
///
/// </קיצער>
[וועבסערוויסע(Namespace = "http://www.conchango.com/")]
[וועבסערוויסעבינדינג(ConformsTo = ווסיפּראָפילעס.באַסיקפּראָפילע1_1)]
עפנטלעך קלאַס ווענדאָרסערוויסע : System.Web.Services.וועבסערוויסע
{

/// <קיצער>
/// Represents a vendor from a custom sharepoint list maintained by MSUSA.
/// </קיצער>
עפנטלעך קלאַס פאַרקויפער
{
עפנטלעך פאַרקויפער() { }

עפנטלעך פאַרקויפער(שפּייַען יניטיטעם)
{
צי (! (יניטיטעם["Vendor Name"] == נול)) VendorName = initItem["Vendor Name"].טאָסטרינג();
צי (! (יניטיטעם["Address 1"] == נול)) VendorAddress1 = initItem["Address 1"].טאָסטרינג();
צי (! (יניטיטעם["Address 2"] == נול)) VendorAddress2 = initItem["Address 2"].טאָסטרינג();
צי (! (יניטיטעם["City"] == נול)) VendorCity = initItem["City"].טאָסטרינג();
צי (! (יניטיטעם["VendorPhone"] == נול)) VendorPhone = initItem["VendorPhone"].טאָסטרינג();
צי (! (יניטיטעם["PurchaseType"] == נול)) VendorType = initItem["PurchaseType"].טאָסטרינג();
צי (! (יניטיטעם["State"] == נול)) VendorState = initItem["State"].טאָסטרינג();
צי (! (יניטיטעם["Zip"] == נול)) VendorZip = initItem["Zip"].טאָסטרינג();
צי (!(יניטיטעם["Fax"] == נול)) VendorFax = initItem["Fax"].טאָסטרינג();
צי (!(יניטיטעם["SalesRepName"] == נול)) VendorSalesRepName = initItem["SalesRepName"].טאָסטרינג();

VendorItemId = initItem.ID; // Unique ID maintained via MOSS.
}

עפנטלעך ינט VendorItemId;
עפנטלעך שטריקל VendorName;
עפנטלעך שטריקל VendorAddress1;
עפנטלעך שטריקל VendorAddress2;
עפנטלעך שטריקל VendorCity;
עפנטלעך שטריקל VendorState;
עפנטלעך שטריקל VendorZip;
עפנטלעך שטריקל VendorPhone;
עפנטלעך שטריקל VendorType;
עפנטלעך שטריקל VendorSalesRepName;
עפנטלעך שטריקל VendorFax;
}

עפנטלעך ווענדאָרסערוויסע () {

//Uncomment the following line if using designed components
//יניטיאַליזעקאָמפּאָנענט();
}

פּריוואַט פאַרקויפער[] GenerateTestVendors()
{
פאַרקויפער[] resultList;
resultList = נייַ פאַרקויפער[100];

פאַרקויפער v;
v = נייַ פאַרקויפער();
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 = נייַ פאַרקויפער();

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 = נייַ פאַרקויפער();
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;

צוריקקומען resultList;

}

[WebMethod]
עפנטלעך פאַרקויפער GetSpecificVendorById(ינט vendorId)
{
שטריקל SpVendorSiteName; // Name of the actual MOSS site that hosts the vendor custom list.
שטריקל SpVendorListName; // Name of the actual MOSS list containing vendors.

SpVendorSiteName = ConfigurationSettings.AppSettings["VendorListHostingSite"].טאָסטרינג();
SpVendorListName = ConfigurationSettings.AppSettings["VendorList"].טאָסטרינג();

ניצן (ספּסיטע site = נייַ ספּסיטע(SpVendorSiteName))
{

ניצן (ספּוועב web = site.OpenWeb())
{

ספּליסט currentList = web.Lists[SpVendorListName];

שפּייַען specificItem = currentList.Items[vendorId];

צוריקקומען נייַ פאַרקויפער(specificItem);

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

}

[WebMethod]
// Assumes that the vendor name is unique, from a business perspective
עפנטלעך פאַרקויפער GetSpecificVendorByVendorName(שטריקל vendorName)
{
שטריקל SpVendorSiteName; // Name of the actual MOSS site that hosts the vendor custom list.
שטריקל SpVendorListName; // Name of the actual MOSS list containing vendors.

SpVendorSiteName = ConfigurationSettings.AppSettings["VendorListHostingSite"].טאָסטרינג();
SpVendorListName = ConfigurationSettings.AppSettings["VendorList"].טאָסטרינג();

ניצן (ספּסיטע site = נייַ ספּסיטע(SpVendorSiteName))
{
ניצן (ספּוועב web = site.OpenWeb())
{

ספּליסט currentList = web.Lists[SpVendorListName];

פאָרעאַטש (שפּייַען vendorItem אין currentList.Items)
{
צי (vendorItem["Vendor Name"] == נול) פאָרזעצן;

צי (vendorItem["Vendor Name"].טאָסטרינג().יקוואַלז(vendorName))
צוריקקומען נייַ פאַרקויפער(vendorItem);
}

פאַרקויפער v = נייַ פאַרקויפער();
v.VendorPhone = "not found: " + vendorName;

צוריקקומען v;

צוריקקומען נול;

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

} // מעטאָד

[WebMethod]
עפנטלעך פאַרקויפער[] GetVendorsOfType (שטריקל filterType)
{

שטריקל SpVendorSiteName; // Name of the actual MOSS site that hosts t
he vendor custom list.
שטריקל SpVendorListName; // Name of the actual MOSS list containing vendors.

SpVendorSiteName = ConfigurationSettings.AppSettings["VendorListHostingSite"].טאָסטרינג();
SpVendorListName = ConfigurationSettings.AppSettings["VendorList"].טאָסטרינג();

פאַרקויפער[] resultList;
ינט vendorIndex = 0;
resultList = נייַ פאַרקויפער[1000];

// Initialize the list with a default friendly message.
פאַרקויפער v = נייַ פאַרקויפער();
v.VendorName = "Select a vendor type to populate this list.";
resultList[0] = v;

// Convert the filter to lower case for easier string comparison later.
filterType = filterType.ToLower();

// If the filter type passed is "test", generate some simple data.
#געגנט Filter type = "test"
צי (פילטערטיפּע.עקוואַלס("test"))
צוריקקומען GenerateTestVendors();
#ענדרעגיאָן

צי (ריכטיק)
{
ניצן (ספּסיטע site = נייַ ספּסיטע(SpVendorSiteName))
{
ניצן (ספּוועב web = site.OpenWeb())
{

v = נול;

ספּליסט currentList = web.Lists[SpVendorListName];

// Iterate through all the items in the vendor list.
פאָרעאַטש (שפּייַען vendorItem אין currentList.Items)
{

שטריקל lowerVendorType;

lowerVendorType = vendorItem["PurchaseType"].טאָסטרינג().טאָלאָווער();
lowerVendorType = lowerVendorType.Substring(3);

צי (lowerVendorType.Equals(filterType))
{
resultList[vendorIndex ] = נייַ פאַרקויפער(vendorItem);
}
} // iterating thru all the vendors in the list


צוריקקומען TrimVendorArray(vendorIndex, resultList);
// return resultList;

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

} // if true

צוריקקומען נול;
}

פּריוואַט פאַרקויפער[] TrimVendorArray(ינט newsize, פאַרקויפער[] originalVendorArray)
{
פאַרקויפער[] trimmedArray;

צי (newsize == 0) newsize = 1;
trimmedArray = נייַ פאַרקויפער[newsize];

ינט currentCounter = 0;

פֿאַר (currentCounter = 0; currentCounter < newsize; currentCounter )
{
trimmedArray[currentCounter] = originalVendorArray[currentCounter];
}

צוריקקומען trimmedArray;

}
}

מאָך: אַבזערוויישאַנז אויף ינפאָפּאַטה דיבאַגינג

ינפאָפּאַטה פאָרעם סערווירער טעות אַרטיקלען זענען מיסלידינג.

בעת אַנטוויקלונג פון אַ ינפאָפּאַטה פאָרעם, איך וואָלט פּאָסטן עס צו מאָך סערווער און צוטריט די פאָרעם. די פאָרעם וואָלט אָנהייבן צו מאַסע און דעמאָלט דזשענערייט אַ מיסלידינג טעות אָנזאָג פּוינטינג מיר צו די פֿענצטער געשעעניש קלאָץ פֿאַר פרטים. אין פאַקט, קיין אָנזאָג איז געווען געשריבן צו די פֿענצטער געשעעניש קלאָץ. גאַנץ, דער אָנזאָג איז געווען געשיקט צו די מאָך אַסקי דיאַגנאָסטיק קלאָץ. איר קענען שפּור אַז אַראָפּ דורך הויפט סערוויסעס אַדמיניסטראַציע.

איר דאַרפֿן צו זייַן שנעל אויף דיין פֿיס. מאָך לייקס צו שרייַבן צו דער קלאָץ טעקע, אָפט און ווערבאָסעלי. This can be trimmed but the default log writing behavior is "everything as quickly as possible".

מאָך: אַפּדייטינג אַ מנהג רשימה

עס זענען פילע גוט ביישפילן פון אַפּדייטינג מנהג רשימות דורך די סדק. דאָ איז נאָך אן אנדער.

ביזנעס פּראָבלעם: ינפאָפּאַטה פאָרעם האט שוין דיזיינד אַז ינייבאַלז ניצערס צו אַרייַן אָנליין קויפן רעקוויסיטיאָנס. פּאָ רעקוויסיטיאָן נומערן זאָל זייַן טראדיציאנעלן סיקוואַנס באזירט ינטאַדזשער וואַלועס און קאַלקיאַלייטיד אויטאָמאַטיש.

ביזנעס סאַלושאַן: שאַפֿן אַ מנהג מאָך רשימה מיט צוויי שפאלטן: "ControlField" and "ControlValue". The value column contains the next purchase requisition number. Note that the generic "control" naming convention provides for future control fields that may be used as needed.

טעכניש סאַלושאַן: Create a web service accessed by the InfoPath client. The web service returns back the next purchase requisition number and updates the value of the list.

Lessons Learned:

  • When adding this web service as a data source to the InfoPath form, I found it necessary to convert it to a udc and store it into a data connection library.
  • I also found it necessary to enable cross domain scripting via central services administration // application management // form server configuration.
  • The first time the form tried to access the web service, it takes a while and on occasion, it would time out. I fiddled with settings in form server configuration to expand the timeout settings and that seemed to help.

די קאָד:

ניצן סיסטעם;
ניצן System.Web;
ניצן System.Web.Services;
ניצן System.Web.Services.Protocols;
ניצן Microsoft.SharePoint;
ניצן System.Configuration;

[וועבסערוויסע(Namespace = "http://www.conchango.com/")]
[וועבסערוויסעבינדינג(ConformsTo = ווסיפּראָפילעס.באַסיקפּראָפילע1_1)]
עפנטלעך קלאַס PoService : System.Web.Services.וועבסערוויסע
{
עפנטלעך PoService () {

//Uncomment the following line if using designed components
//יניטיאַליזעקאָמפּאָנענט();
}

/// <קיצער>
/// Obtain the next PO number from the sharepoint po number control list.
/// Increment the PO number in that list.
/// </קיצער>
/// <returns></returns>
[WebMethod]
עפנטלעך שטריקל GetNextPoNumber()
{
שטריקל ספּפּאָקאָנטראָלסיטענאַמע; // Name of the actual MOSS site that hosts the PO Control list.
שטריקל ספּפּאָקאָנטראָלליסטנאַמע; // Name of the actual MOSS list containing the Po control.

SpPoControlSiteName = ConfigurationSettings.AppSettings["PoControlListHostingSite"].טאָסטרינג();
SpPoControlListName = ConfigurationSettings.AppSettings["PoControlList"].טאָסטרינג();

שטריקל nextPoReqNumber = "xyzzy";

ניצן (ספּסיטע site = נייַ ספּסיטע(ספּפּאָקאָנטראָלסיטענאַמע))
{
ניצן (ספּוועב web = site.OpenWeb())
{

ספּליסט currentList = web.Lists[ספּפּאָקאָנטראָלליסטנאַמע];

פאָרעאַטש (שפּייַען קאָנטראָליטעם אין currentList.Items)
{

צי (((שטריקל)קאָנטראָליטעם["ControlField"]).יקוואַלז("NextPoNumber"))
{
nextPoReqNumber = (שטריקל)קאָנטראָליטעם["ControlValue"];

ינט int_nextPoReqNumber;
int_nextPoReqNumber = גער.טאָינט32(nextPoReqNumber);

int_nextPoReqNumber ;

קאָנטראָליטעם["ControlValue"] = int_nextPoReqNumber;
controlItem.Update();
}

} // Locating, reading and updating the PO number in the list.


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

צוריקקומען nextPoReqNumber;

}
}