Friday, April 29, 2005
InfoPath text box handling of TAB and other whitespace
In addition, I could not enter TABs in the text box using the keyboard. The same thing happend with \t characters added to strings in the form code (JScript).
I inspected the properties of the text box, and the only formatting option available is "Paragraph breaks". As my options were limited, I chose that option and re-loaded the XML data. I was mildly delighted when all the alignment stuff in the string data were displayed correctly, including the TAB characters. I can now also enter TABs from the keyboard using CTRL-TAB.
The InfoPath team has blogged about line breaks (CR LF \r \n), and they outline how to make these formatting characters available in rules. Their solution should also be applicable to TAB.
Thursday, April 28, 2005
Submitting xsi:nil="true" values from InfoPath to ASP.NET 1.x web services
- make non-string data types such as xs:date and xs:decimal truly optional in InfoPath
- submit data to the web service by modifing the XML data in OnSubmitRequest to circumvent the missing support for nillable in .NET 1.x ASP.NET web services
The first issue is caused by the fact that ASP.NET 1.x web service by design do not support nillable elements in the web service parameters. Check the <wsdl:types> element of any ASMX WSDL, and you will not find any nillable="true" elements even if your data XSD contains such elements. The reason for this is the lack of support for NULL in .NET 1.x value types. ASP.NET 2.0 web services will support nillable="true".
After modifying the underlying XSD schemas of your InfoPath as outlined in my previous post to manually re-introduce the nillable="true" attributes, the fields can be left empty in your form. But you will not be able to sumbit the form to the web service. The SOAP request will fail like this:
The SOAP response indicates that an error occurred:
Server was unable to read request. --> There is an error in XML document (47, 104). --> Input string was not in a correct format.
This is caused by this kind of element in the submitted XML:
<s1:Amount xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"></s1:Amount>
The web service is not able to deserialize this element into a value type due to the lack of support for nillable. Thus, the XML data must be modified before submitting the data to the web service.
InfoPath allows you to use the OnSubmitRequest event to write your own script for submitting the forms data. This event is only available by using Tools-Submitting Forms and selecting "Custom submit using form code" in the 'Submit to' dropdown. Check the 'Edit Form Code' checkbox and click OK to add an event handler for OnSubmitRequest.
This example shows how to look for all instances of a specific element that is NULL, remove the nil attribute and set a dummy value, and finally submitting the form using code:
function XDocument::OnSubmitRequest(eventObj)
{
try
{
var submitDataSource = "Main submit";
//debugger
//get a collection of
var nodeList = XDocument.DOM.selectNodes("/dfs:myFields/dfs:dataFields//s1:Amount[@xsi:nil='true']");
//iterate the list and
//
for(var i=0; i < nodeList.length; i++)
//put zero into the element
//
// The xsi:nil needs to be removed before we set the value.
xmlNode.removeAttribute("xsi:nil");
// Setting the value will mark the document as dirty.
xmlNode.text = -1; //biz logic will interpret this as NULL
}
//call the Submit method of the
//
XDocument.DataAdapters(submitDataSource).Submit();
eventObj.ReturnStatus = true;
}
catch(ex)
{
XDocument.UI.Alert("Failed while sending the request.\r\n" + ex.number + " - " + ex.description);
eventObj.ReturnStatus = false;
}
}
Tuesday, April 26, 2005
MSCRM ColumnSet XSD: fields, sorting & filtering
It was not until I needed to sort the result set, that I started to look for how to make the MSCRM services perform sorting, to avoid sorting the result set with a DataView connected to our typed DataSet. By chance, I browsed to the schema of the ColumnSet parameter, and found out that it allows you to specify several clauses for the retrieve operation: select fields, specify sorting, apply filters, etc.
This is an example of how to retrieve a light-weight, sorted and filtered list of sub-accounts:
//fields, sorting, filterstring colset = "<columnset>";
colset += "<column>accountid</column>";
colset += "<column>name</column>";
colset += "<column>emailaddress1</column>";
colset += "<column>ownerid</column>";
//sort on name
colset += "<ascend>name</ascend>";
//only active accounts
colset += "<filter column='statecode' operator='eq' value='" + Microsoft.Crm.Platform.Types.ACCOUNT_STATE.AS_ACTIVE + "' />";
colset += "</colset>";
//retrieve sub accounts
_crmAccount.RetrieveSubAccounts(_crmUserAuth, accountId, colset)
Note that you must specify one or more <column> elements to get data back, as the MSCRM services will return no fields if you do not specify any.
The services do, however, behave very nicely when specifying a column that is a relation to e.g. the biz user that owns an account (ownerid), as not only the owner GUID is returned, but it is also annotated with XML attributes containing the full name of the owner, etc. These extra attributes saves you from doing extra lookups in MSCRM to present human-readable data to the user.
Refer to the SDK for more information about the ColumnSet XML Schema.Thursday, April 21, 2005
Optional numeric fields in InfoPath
Today I took a closer look at this problem, and instead of starting with the service contract (WSCF) and creating an InfoPath form based on the generated web service, I designed a new form from scratch by building the data source (XSD schema) using InfoPath. And, lo and behold, the decimal fields added manually to the data source are by default optional! The 'Cannot be blank' checkbox is enabled and unchecked!
I extracted the form files and inspected the XSD schema, and the element had both minOccurs="0" and nillable="true". Just as I had defined the decimal elements in the XSD schemas used in my service contract. So, why the different behavior ?
To find out why, I opened one of the InfoPath forms made by connecting to a WSCF web service and then extracted the form files. When I inspected the schemas, the nillable="true" was not in the XSD schema induced by InfoPath. By adding the attribute manually to the schema and then opening the form definition file (.XSF) with InfoPath, the problem was solved and my decimal fields are now truly optional in InfoPath. Note that this fix will be gone as soon as you re-induce the data source schemas.
Is this a bug with regards to nillable in the generated WSDL, web service or just the way it is ? Or, more likely, a weakness in InfoPath ? To be continued...