I posted a classified ad for selling my car in Bergen county, NJ on Sunday night. I received several inquiries via email shortly thereafter and closed the deal with someone on Tuesday night.
Almost too good to be true …
I posted a classified ad for selling my car in Bergen county, NJ on Sunday night. I received several inquiries via email shortly thereafter and closed the deal with someone on Tuesday night.
Almost too good to be true …
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.
Business Scenario:
Enterprise-wide implementation of MOSS for manufacturing company with 30+ sites and a few dozen corporate departments.
Business Objective:
Despite a multitude of business groups (departments, locations, etc), certain data should be maintained at a global level. For example, an authoritative master list of all physical locations of the company (e.g. manufacturing facilities, warehouse locations, sales offices) should be maintained in a central location.
Technical Problem:
The enterprise taxonomy was implemented using multiple site collections. We would have liked to create the authoritative list of physical locations in a custom WSS list. Then, when we needed to have a column in a content type (or a column added to a list or doc library) that contained corporate locations, we would create a column using the "lookup" datatype and point to this master list.
Unfortunately, lookup datatypes must access a source list "locally" meaning that our authoritative list cannot span site collections.
Technical Solution:
Implement a new custom data type implemented based on SPField and represented as a DropDownList in the UI whose ListItems populate from the master WSS list.
We created a new site collection called "http://localhost/EnterpriseData". There, we created a custom list named "Corporate Locations". This list just uses the standard "Title" field to contain the list of actual corporate locations.
One follows several discrete steps to create a custom data type in WSS. They are:
Here is the code for that:
public class XYZZYCorporateLocationField : SPFieldText
{
public XYZZYCorporateLocationField
(SPFieldCollection fields, string typeName, string displayName)
: base(fields, typeName, displayName) { }
public XYZZYCorporateLocationField
(SPFieldCollection fields, string displayName)
: base(fields, displayName) { }
public override BaseFieldControl FieldRenderingControl
{
get
{
BaseFieldControl control = new XYZZYCorporateLocationFieldControl();
control.FieldName = this.InternalName;
return control;
} //get
} // fieldrenderingcontrol
public override string GetValidatedString(object value)
{
if (this.Required || value.ToString().Equals(String.Empty))
{
throw new SPFieldValidationException ("Department is not assigned.");
}
return base.GetValidatedString(value);
} // getvalidatedstring
} // XYZZYCorporateLocation
public class XYZZYCorporateLocationFieldControl : BaseFieldControl
{
protected DropDownList XYZZYCorporateLocationSelector;
protected override string DefaultTemplateName
{
get
{
return "XYZZYCorporateLocationFieldControl";
}
} // DefaultTemplateName
public override object Value
{
get
{
EnsureChildControls();
return this.XYZZYCorporateLocationSelector.SelectedValue;
} // get
set
{
EnsureChildControls();
this.XYZZYCorporateLocationSelector.SelectedValue = (string)this.ItemFieldValue;
} // set
} // override object Value
protected override void CreateChildControls()
{
if (this.Field == null || this.ControlMode == SPControlMode.Display)
return;
base.CreateChildControls();
this.XYZZYCorporateLocationSelector =
(DropDownList)TemplateContainer.FindControl("XYZZYCorporateLocationSelector");
if (this.XYZZYCorporateLocationSelector == null)
throw new Exception("ERROR: Cannot load .ASCX file!");
if (!this.Page.IsPostBack)
{
using (SPSite site = new SPSite("http://localhost/enterprisedata"))
{
using (SPWeb web = site.OpenWeb())
{
SPList currentList = web.Lists["Corporate Locations"];
foreach (SPItem XYZZYCorporateLocation in currentList.Items)
{
if (XYZZYCorporateLocation["Title"] == null) continue;
string theTitle;
theTitle = XYZZYCorporateLocation["Title"].ToString();
this.XYZZYCorporateLocationSelector.Items.Add
(new ListItem(theTitle, theTitle));
} // foreach
} // using spweb web = site.openweb()
} // using spsite site = new spsite("http://localhost/enterprisedata")
} // if not a postback
} // CreateChildControls
} // XYZZYCorporateLocationFieldControl
The above code basically implements the logic for populating the DropDownList with values from the WSS custom list located at http://localhost/enterprisedata and named "Corporate Departments".
I defined both classes in a single .cs file, compiled it and put it into the GAC (strong required, of course).
<%@ Control Language="C#" Inherits="Microsoft.SharePoint.Portal.ServerAdmin.CreateSiteCollectionPanel1,Microsoft.SharePoint.Portal,Version=12.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" compilationMode="Always" %>
<%@ Register Tagprefix="wssawc" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<SharePoint:RenderingTemplate ID="XYZZYCorporateLocationFieldControl" runat="server">
<Template>
<asp:DropDownList ID="XYZZYCorporateLocationSelector" runat="server" />
</Template>
</SharePoint:RenderingTemplate>
The above is saved into c:\program files\common files\microsoft shared\web server extensions\12\controltemplates.
<?xml version="1.0" encoding="utf-8" ?>
<FieldTypes>
<FieldType>
<Field Name="TypeName">CorporateLocations</Field>
<Field Name="ParentType">Text</Field>
<Field Name="TypeDisplayName">Corporate Locations</Field>
<Field Name="TypeShortDescription">All XYZZY Corporate locations including manufacturing or other facilities.</Field>
<Field Name="UserCreatable">TRUE</Field>
<Field Name="ShowInListCreate">TRUE</Field>
<Field Name="ShowInDocumentLibraryCreate">TRUE</Field>
<Field Name="ShowInSurveyCreate">TRUE</Field>
<Field Name="ShowInColumnTemplateCreate">TRUE</Field>
<Field Name="FieldTypeClass">Conchango.XYZZYCorporateLocationField, XYZZYCorporateLocationField, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b0b19e85410990c4</Field>
<RenderPattern Name="DisplayPattern">
<Switch>
<Expr>
<Column />
</Expr>
<Case Value=""/>
<Default>
<HTML>
<![CDATA[<span style="color:Red"><b>]]>
</HTML>
<Column SubColumnNumber="0" HTMLEncode="TRUE"/>
<HTML><![CDATA[</b></span>]]></HTML>
</Default>
</Switch>
</RenderPattern>
</FieldType>
</FieldTypes>
This XML file adds the custom data type to the WSS "library" and matches it up against the GAC’d assembly.
After moving all these bits into place, iisreset on the server and it should all start working nicely.
Additional category: CAML
Here is a great posting by a fellow named "craig" on a technique for finding CAML definitions for field content types based off real live definitions from a site.
His posting says it all. In brief:
Additional categories: Visual Studio 2005
To enable useful intellisense for Features, elements, etc in visual studio 2005:
Intellisense is now enabled for that XML document.
See here for more information on this subject and for instructions on how to automatically associate WSS intellisense with any XML file.
I took and passed the above mentioned test this morning. I found the exam to be difficult and fair.
There is a relative dearth of information on this exam on the web. I’m not sure why.
I obviously won’t get into any detail about the exam I took, but I think I can safely say the following:
It lists what you need to know to pass the exam and it’s, IMO, very accurate.
</end>Subscribe to my blog!
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.
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.