Category Archives: MOSS

MOSS advanced search customization — Case does matter in advanced search XSLT

I don’t modify advanced search XSLT very often, so it seems like I’m climbing small hills every time.

My newest lesson is this: Case matters when referencing a column. In my advanced search, I have columns defined as this:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <
Columns>
    <
Column Name="GafTrainingInvoiceNumber" />
    <
Column Name="GafTrainingInvoiceLocation" />
    <
Column Name="WorkId"/>
    <
Column Name="Rank"/>
    <
Column Name="Title"/>
    <
Column Name="Author"/>
    <
Column Name="Size"/>
    <
Column Name="Path"/>
    <
Column Name="Description"/>
    <
Column Name="Write"/>
    <
Column Name="SiteName"/>
    <
Column Name="CollapsingStatus"/>
    <
Column Name="HitHighlightedSummary"/>
    <
Column Name="HitHighlightedProperties"/>
    <
Column Name="ContentClass"/>
    <
Column Name="IsDocument"/>
    <
Column Name="PictureThumbnailURL"/>
  </
Columns>
</
root>

The XLST that displays the invoice number and invoice location had been:

    <p>
      Training Invoice Number: <xsl:value-of select="GafTrainingInvoiceNumber"/>
      <
br></br>
      Training Invoice Location: <xsl:value-of select="GafTrainingInvoiceLocation"/>
    </
p>

However, the select has to reference the property in all lower case, as in:

    <p>
      Training Invoice Number: <xsl:value-of select="gaftraininginvoicenumber"/>
      <
br></br>
      Training Invoice Location: <xsl:value-of select="gaftraininginvoicelocation"/>
    </
p>

    
 

Until I corrected that, search results showed the labels (i.e. "Training Invoice Number") but no data.

 

MOSS / InfoPath Forms Server (InfoPath 2007) drop-down list performance

Additional category: InfoPath

Summary: An InfoPath 2007 form deployed to a MOSS server provides a drop-down list of vendors tied to a custom MOSS list. Upon selecting a vendor, rules assign field values to a handful of text fields such as sales rep name, address, city, state, zip and phone. Performance is horrible. We notice that performance gets worse (in a non-linear fashion) for each additional field we update this way. I.e., if we just update the sales rep name, it takes [x] amount of time. If we update sales rep, address1, address2, city, state, zip, it takes 10 times longer.

Solution: Write a web service (sample code can be found here) that is passed in the name of a vendor and it returns back the vendor details. Then, assign the fields this way. Although this too seems slow, there was no discernable difference in performance when we assigned 1 field versus 8 fields. As an added bonus, users get a cool "contacting the server" Cylon effect while they wait for the form to invoke and consume the service results.

MOSS: Exception occurred. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION))

UPDATE: We never determined the root cause of this problem and it never surface again.

We notice during implementation of a development site that suddenly, two users are unable to access a site collection. Those accounts can authenticate to the main site, but when trying to access a particular site collection, they just get a blank screen. No errors displayed, just a white blank page.

We log in as a site collection admin and try to add one of those users as a site admin and this time, upon pressing "OK", we get this message:

Exception occurred. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION))

We spent some time researching this and unfortunately, didn’t come up with anything useful. There were some messages in the diagnostic log, but it was hard to exactly correlate them with this issue.

In the end, we deleting the site collection and re-created it and that solved it.

If I figure out what caused this in future, I’ll update this post.

 

MOSS: Iterating through custom lists and returning filtered data to InfoPath

Business Scenario:

Provide a method that enables users to enter accurate purchase requisitions quickly.

Business problem:

The client does business with several hundred vendors.

Vendors are "type" specific. This means that a vendor sells computer equipment (e.g. Dell) or office supplies (e.g. Staples).

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

Business Solution:

Differentiate vendors in the system via "type".

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

Technical Solution:

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

Two InfoPath selection lists control vendor selection. First, 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:

  • First, 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. However, 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. Therefore, it was necessary to implement the web service.
  • This is a classic "cascading selection list" problem in the InfoPath forms server world and there are many good examples out there that explain how to solve this.
  • A blank value for a column in the vendor list does not return an empty string when referenced like this: initItem["Vendor Name"]. Instead, it returns a null.

Some other Notes:

  • I return an array[] of vendors because I had some difficulty returning an ArrayList. InfoPath was complaining about it and I didn’t have the time or the inclination to fight over it. This, of course, puts an artificial limit on the total number of vendors. It also compelled me to implement a trim() method on the array because I hate the idea of returning back 100’s of null vendors. InfoPath doesn’t care, but it nagged at me. (Again, this was easier than fighting InfoPath over ArrayLists).
  • I implemented a GetSpecificVendorByName() function as well, which may be instructive.

The code:

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using Microsoft.SharePoint;
using System.Configuration;

/// <summary>
///
 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.
/// 
/// </summary>
[WebService(Namespace = "http://www.conchango.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class VendorService : System.Web.Services.WebService
{

    /// <summary>
    /// Represents a vendor from a custom sharepoint list maintained by MSUSA.
    /// </summary>
    public class Vendor
    {
        public Vendor() { }

        public Vendor(SPItem initItem)
        {
            if (! (initItem["Vendor Name"] == null)) VendorName = initItem["Vendor Name"].ToString();
            if (! (initItem["Address 1"] == null)) VendorAddress1 = initItem["Address 1"].ToString();
            if (! (initItem["Address 2"] == null)) VendorAddress2 = initItem["Address 2"].ToString();
            if (! (initItem["City"] == null)) VendorCity = initItem["City"].ToString();
            if (! (initItem["VendorPhone"] == null)) VendorPhone = initItem["VendorPhone"].ToString();
            if (! (initItem["PurchaseType"] == null)) VendorType = initItem["PurchaseType"].ToString();
            if (! (initItem["State"] == null)) VendorState = initItem["State"].ToString();
            if (! (initItem["Zip"] == null)) VendorZip = initItem["Zip"].ToString();
            if (!(initItem["Fax"] == null)) VendorFax = initItem["Fax"].ToString();
            if (!(initItem["SalesRepName"] == null)) VendorSalesRepName = initItem["SalesRepName"].ToString();
            
            VendorItemId = initItem.ID; // Unique ID maintained via MOSS.
        }

        public int VendorItemId;
        public string VendorName;
        public string VendorAddress1;
        public string VendorAddress2;
        public string VendorCity;
        public string VendorState;
        public string VendorZip;
        public string VendorPhone;
        public string VendorType;
        public string VendorSalesRepName;
        public string VendorFax;
    }

    public VendorService () {

        //Uncomment the following line if using designed components 
        //InitializeComponent(); 
    }

    private Vendor[] GenerateTestVendors()
    {
        Vendor[] resultList;
        resultList = new Vendor[100];

        Vendor v;
        v = new Vendor();
        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 = new Vendor();

        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 = new Vendor();
        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;

        return resultList;

    }

    [WebMethod]
    public Vendor GetSpecificVendorById(int vendorId)
    {
        string SpVendorSiteName; // Name of the actual MOSS site that hosts the vendor custom list.
        string SpVendorListName; // Name of the actual MOSS list containing vendors.

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

        using (SPSite site = new SPSite(SpVendorSiteName))
        {

            using (SPWeb web = site.OpenWeb())
            {

                SPList currentList = web.Lists[SpVendorListName];

                SPItem specificItem = currentList.Items[vendorId];

                return new Vendor(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
    public Vendor GetSpecificVendorByVendorName(string vendorName)
    {
        string SpVendorSiteName; // Name of the actual MOSS site that hosts the vendor custom list.
        string SpVendorListName; // Name of the actual MOSS list containing vendors.

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

        using (SPSite site = new SPSite(SpVendorSiteName))
        {
            using (SPWeb web = site.OpenWeb())
            {

                SPList currentList = web.Lists[SpVendorListName];

                foreach (SPItem vendorItem in currentList.Items)
                {
                    if (vendorItem["Vendor Name"] == nullcontinue;

                    if (vendorItem["Vendor Name"].ToString().Equals(vendorName))
                        return new Vendor(vendorItem);
                }

                Vendor v = new Vendor();
                v.VendorPhone = "not found: " + vendorName;

                return v;

                return null;

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

    } // method

    [WebMethod]
    public Vendor[] GetVendorsOfType (string filterType)
    {

        string SpVendorSiteName; // Name of the actual MOSS site that hosts t
he vendor custom list.
        string SpVendorListName; // Name of the actual MOSS list containing vendors.

        SpVendorSiteName = ConfigurationSettings.AppSettings["VendorListHostingSite"].ToString();
        SpVendorListName = ConfigurationSettings.AppSettings["VendorList"].ToString();
        
        Vendor[] resultList;
        int vendorIndex = 0;
        resultList = new Vendor[1000];

        // Initialize the list with a default friendly message.
        Vendor v = new Vendor();
        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.
        #region Filter type = "test"
        if (filterType.Equals("test"))
            return GenerateTestVendors();
        #endregion

        if (true)
        {
            using (SPSite site = new SPSite(SpVendorSiteName))
            {
                using (SPWeb web = site.OpenWeb())
                {

                    v = null;

                    SPList currentList = web.Lists[SpVendorListName];
                    
                    // Iterate through all the items in the vendor list.
                    foreach (SPItem vendorItem in currentList.Items)
                    {

                        string lowerVendorType;

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

                        if (lowerVendorType.Equals(filterType))
                        {
                            resultList[vendorIndex++] = new Vendor(vendorItem);
                        }
                    } // iterating thru all the vendors in the list

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

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

        } // if true

        return null;
    }

    private Vendor[] TrimVendorArray(int newsize, Vendor[] originalVendorArray)
    {
        Vendor[] trimmedArray;

        if (newsize == 0) newsize = 1;
        trimmedArray = new Vendor[newsize];

        int currentCounter = 0;

        for (currentCounter = 0; currentCounter < newsize; currentCounter++)
        {
            trimmedArray[currentCounter] = originalVendorArray[currentCounter];
        }

        return trimmedArray;

    }
}