Not getting values of fields of types Droplist and TreeList from Lucene index - lucene

I am using Sitecore 7.2. I created a custom Lucene index.
While I am able to get the values of fields of type Single-line Text, Rich Text & DateTime, I am not getting the values of fields of types such as Droplist and TreeList.
I have tried changing the indexType of these fields to "UNTOKENISED" but still continue to get this issue. I also checked my index using Luke and observed that only the Title, Summary and Body fields are part of the index.
Below is the portion of my index configuration where I've defined my fields. products and type are Treelist and Droplist fields respectively.
<fieldMap type="Sitecore.ContentSearch.FieldMap, Sitecore.ContentSearch">
<fieldNames hint="raw:AddFieldByFieldName">
<field fieldName="title" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.String" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider">
<analyzer type="Sitecore.ContentSearch.LuceneProvider.Analyzers.LowerCaseKeywordAnalyzer, Sitecore.ContentSearch.LuceneProvider" />
</field>
<field fieldName="summary" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.String" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider">
<analyzer type="Sitecore.ContentSearch.LuceneProvider.Analyzers.LowerCaseKeywordAnalyzer, Sitecore.ContentSearch.LuceneProvider" />
</field>
<field fieldName="body" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.String" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider">
<analyzer type="Sitecore.ContentSearch.LuceneProvider.Analyzers.LowerCaseKeywordAnalyzer, Sitecore.ContentSearch.LuceneProvider" />
</field>
<field fieldName="datemodified" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.String" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider">
<analyzer type="Sitecore.ContentSearch.LuceneProvider.Analyzers.LowerCaseKeywordAnalyzer, Sitecore.ContentSearch.LuceneProvider" />
</field>
<field fieldName="products" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.String" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider">
<analyzer type="Sitecore.ContentSearch.LuceneProvider.Analyzers.LowerCaseKeywordAnalyzer, Sitecore.ContentSearch.LuceneProvider" />
</field>
<fieldType fieldName="type" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.String"
settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider" />
</fieldNames>
</fieldMap>
The class I am using to fetch values from the index is as below:
public class DownloadResult : SearchResultItem
{
[IndexField("title")]
public string Title { get; set; }
[IndexField("summary")]
public string Summary { get; set; }
[IndexField("type")]
public string Type { get; set; }
[IndexField("body")]
public string Body { get; set; }
[IndexField("datemodified")]
public DateTime DateModified { get; set; }
[indexfield("products")]
public string products { get; set; }
}

In the file Sitecore.ContentSearch.Lucene.DefaultIndexConfiguration.config
you need to have next fieldReaders for indexing droplist,treelist,etc.
These are default configuration in Sitecore:
<fieldReader fieldTypeName="checklist|multilist|treelist|treelistex|tree list" fieldNameFormat="{0}" fieldReaderType="Sitecore.ContentSearch.FieldReaders.MultiListFieldReader, Sitecore.ContentSearch" />
<fieldReader fieldTypeName="icon|droplist|grouped droplist" fieldNameFormat="{0}" fieldReaderType="Sitecore.ContentSearch.FieldReaders.DefaultFieldReader, Sitecore.ContentSearch" />
<fieldReader fieldTypeName="name lookup value list|name value list" fieldNameFormat="{0}" fieldReaderType="Sitecore.ContentSearch.FieldReaders.NameValueListFieldReader, Sitecore.ContentSearch" />
<fieldReader fieldTypeName="droplink|droptree|grouped droplink|tree" fieldNameFormat="{0}" fieldReaderType="Sitecore.ContentSearch.FieldReaders.LookupFieldReader, Sitecore.ContentSearch" />
please check if you have these configurations and if you reference this config file into your custom index file.

You should use computed index fields to get such fields (Treelist and Droplist) indexed.
Reference for HowTo : How to Add Computed Index

Try declaring your fields like this, this always works for me:
[IndexField("products")]
public IEnumerable<ID> Products { get; set; }
[IndexField("type")]
public IEnumerable<ID> Type { get; set; }
You could also try adjusting the storage type settings in the AddFieldByFieldTypeName settings
<fieldType fieldTypeName="droptree" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.String" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider" />

please check your search's default configuration file for fieldtypes "DropList" and "TreeList". If its not added please add it: It will look something like this:
<fieldTypes hint="raw:AddFieldTypes">
…
<fieldType name="droplist" storageType="NO" indexType="TOKENIZED" vectorType="NO" boost="1f" />
<fieldType name="treelist" storageType="NO" indexType="TOKENIZED" vectorType="NO" boost="1f" />
…
</fieldTypes>

(Not able to comment on Sairaj's answer)
While indexAllFields is a solution it is not ideal. The real problem I assume (since it happened to us) is that you are trying to index a field in which it's value is pulled from standard values. While viewing the item in Content Editor, it looks to have a value, but per Lucene (don't ask my why) it does not have a value.
Apparently Lucene does not read a fields value from standard values unless you tell it to indexAllFields. While a custom field could also be used to solve this problem, I feel like this is either A) a bug in Sitecore or B) a configuration option that no one has been able to track down.
(Edit)
We noticed this on 8.1

After trying out all the different suggestions and hitting a blank, I changed the value of indexAllFields to true in the configuration. That solved it.

Related

index rich documents using solrcell and tika

I am a newbee in Solr search and currently working to get solr Cell work with Tika. Consider the following text file:
Name: Popeye
Nationality: American
I would like Solr to return me two fields named 'name' and 'nationality' with the values popeye and american. To do this, I define two fields in my schema.xml file as
<field name="name" type="text_general" indexed="true" stored="true"/>
<field name="nationality" type="text_general" indexed="true" stored="true"/>
The text_general field is defined as
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
<!-- in this example, we will only use synonyms at query time
<filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
-->
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
In the solrconfig.xml file, I define the update/extract method
<requestHandler name="/update/extract" class="solr.extraction.ExtractingRequestHandler" >
<lst name="defaults">
<str name="lowernames">true</str>
<str name="uprefix">attr_</str>
<str name="captureAttr">true</str>
Finally, I run the command to index the document as
curl 'http://localhost:8983/solr/popeye_bio_collection_shard1_replica1/update/extract?literal.id=doc1&commit=true' -F "myfile=#/tmp/popeye_bio.txt"
The document gets indexed without error. When I use the query command as
curl 'http://localhost:8983/solr/popeye_bio_collection_shard1_replica1/select?q=*%3A*&wt=json&indent=true'
I get the output as
{
"responseHeader":{
"status":0,
"QTime":3,
"params":{
"indent":"true",
"q":"*:*",
"wt":"json"}},
"response":{"numFound":1,"start":0,"docs":[
{
"attr_meta":["stream_source_info",
"myfile",
"stream_content_type",
"text/plain",
"stream_size",
"206",
"Content-Encoding",
"windows-1252",
"stream_name",
"popeye_bio.txt",
"Content-Type",
"text/plain; charset=windows-1252"],
"id":"doc1",
"attr_stream_source_info":["myfile"],
"attr_stream_content_type":["text/plain"],
"attr_stream_size":["206"],
"attr_content_encoding":["windows-1252"],
"attr_stream_name":["popeye_bio.txt"],
"attr_content_type":["text/plain; charset=windows-1252"],
"attr_content":[" \n \n \n \n \n \n \n \n \n \n Name: Popeye\r\nNationality: American\r\n \n "],
"_version_":1567726521681969152}]
}}
As you can see, popeye and american are not indexed in the fields I have defined in the schema.xml file. What am I doing wrong here? I have tried changing the tokenizer as in text_general field type as <tokenizer class="solr.PatternTokenizerFactory" pattern=": "/>. But it does not make any difference. I would appreciate any help in this regard!
When you define a tokenizer you're just indicating to Solr that all the data that is sent in that field should be tokenized/processed with your configuration, but in the end, you're sending all your information into one field.
Solr assumes that your data is structured (1 document that has fields). So one analyzer/tokenizer can't create more fields. The function of an analyzer/tokenizer is basically just tokenizing and transforming the text that is going into the inverted index for searching.
What you can do is use the ScriptUpdateProcessor and define a pipeline to do your modifications (split one field into several) before the text get's into the tokenizer. Something like:
<processor class="solr.StatelessScriptUpdateProcessorFactory">
<str name="script">splitField.js</str>
</processor>
And the splitField.js file could have something like:
function processAdd(cmd) {
doc = cmd.solrDoc; // org.apache.solr.common.SolrInputDocument
field = doc.getFieldValue("attr_content");
// split your attr_content text into two variables:
// name and nationality, then
doc.setField("name", name);
doc.setField("nationality", nationality);
}
In an ideal world this should be handled outside of Solr, but with the ScriptUpdateProcessor you can accomplish what you want.
The way I currently do it is to define a ´update.chain´ inside the update/extract method
<requestHandler name="/update/extract" class="solr.extraction.ExtractingRequestHandler" >
<lst name="defaults">
<str name="update.chain">mychain</str>
<str name="lowernames">true</str>
<str name="uprefix">attr_</str>
<str name="captureAttr">true</str>
where mychain is
<updateRequestProcessorChain name="mychain">
<processor class="solr.StatelessScriptUpdateProcessorFactory">
<str name="script">splitField.js</str>
</processor>
<processor class="solr.LogUpdateProcessorFactory" />
<processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>
I included it inside the update/extract method, so that the processor gets called. If I understand you correctly, I should call the processor after update/extract method and before the text is sent to the tokenizer. If so, then how would the processor be called?
I also tried removing the <str name="update.chain">mychain</str> line from update/extract and then calling
curl 'http://localhost:8983/solr/popeye_bio_collection_shard1_replica1/update/extract?literal.id=doc1&update.chain=mychain&commit=true' -F "myfile=#/tmp/popeye_bio.txt"
I get the same error. splitFiled.js is defined as
function processAdd(cmd) {
doc = cmd.solrDoc; // org.apache.solr.common.SolrInputDocument
field = doc.getFieldValue("attr_content");
// split your attr_content text into two variables:
// name and nationality, then
doc.setField("name", name);
doc.setField("nationality", nationality);
}
function processDelete(cmd) {
}
function processMergeIndexes(cmd) {
}
function processCommit(cmd) {
}
function processRollback(cmd) {
}
function finish() {
}
The error occurs in the setFieldline. Is there any way I could print the ´field´ in console? Perhaps, ´console.log´ method?

Sitecore custom index configure languages

I created a custom Lucene index in a Sitecore 8.1 environment like this:
<?xml version="1.0"?>
<configuration xmlns:x="http://www.sitecore.net/xmlconfig/">
<sitecore>
<contentSearch>
<configuration type="Sitecore.ContentSearch.ContentSearchConfiguration, Sitecore.ContentSearch">
<indexes hint="list:AddIndex">
<index id="Products_index" type="Sitecore.ContentSearch.LuceneProvider.LuceneIndex, Sitecore.ContentSearch.LuceneProvider">
<param desc="name">$(id)</param>
<param desc="folder">$(id)</param>
<param desc="propertyStore" ref="contentSearch/indexConfigurations/databasePropertyStore" param1="$(id)" />
<configuration ref="contentSearch/indexConfigurations/ProductIndexConfiguration" />
<strategies hint="list:AddStrategy">
<strategy ref="contentSearch/indexConfigurations/indexUpdateStrategies/onPublishEndAsync" />
</strategies>
<commitPolicyExecutor type="Sitecore.ContentSearch.CommitPolicyExecutor, Sitecore.ContentSearch">
<policies hint="list:AddCommitPolicy">
<policy type="Sitecore.ContentSearch.TimeIntervalCommitPolicy, Sitecore.ContentSearch" />
</policies>
</commitPolicyExecutor>
<locations hint="list:AddCrawler">
<crawler type="Sitecore.ContentSearch.SitecoreItemCrawler, Sitecore.ContentSearch">
<Database>master</Database>
<Root>/sitecore/content/General/Product Repository</Root>
</crawler>
</locations>
<enableItemLanguageFallback>false</enableItemLanguageFallback>
<enableFieldLanguageFallback>false</enableFieldLanguageFallback>
</index>
</indexes>
</configuration>
<indexConfigurations>
<ProductIndexConfiguration type="Sitecore.ContentSearch.LuceneProvider.LuceneIndexConfiguration, Sitecore.ContentSearch.LuceneProvider">
<initializeOnAdd>true</initializeOnAdd>
<analyzer ref="contentSearch/indexConfigurations/defaultLuceneIndexConfiguration/analyzer" />
<documentBuilderType>Sitecore.ContentSearch.LuceneProvider.LuceneDocumentBuilder, Sitecore.ContentSearch.LuceneProvider</documentBuilderType>
<fieldMap type="Sitecore.ContentSearch.FieldMap, Sitecore.ContentSearch">
<fieldNames hint="raw:AddFieldByFieldName">
<field fieldName="_uniqueid" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.String" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider">
<analyzer type="Sitecore.ContentSearch.LuceneProvider.Analyzers.LowerCaseKeywordAnalyzer, Sitecore.ContentSearch.LuceneProvider" />
</field>
<field fieldName="key" storageType="YES" indexType="UNTOKENIZED" vectorType="NO" boost="1f" type="System.String" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider"/>
</fieldNames>
</fieldMap>
<documentOptions type="Sitecore.ContentSearch.LuceneProvider.LuceneDocumentBuilderOptions, Sitecore.ContentSearch.LuceneProvider">
<indexAllFields>true</indexAllFields>
<include hint="list:AddIncludedTemplate">
<Product>{843B9598-318D-4AFA-B8C8-07E3DF5C6738}</Product>
</include>
</documentOptions>
<fieldReaders ref="contentSearch/indexConfigurations/defaultLuceneIndexConfiguration/fieldReaders"/>
<indexFieldStorageValueFormatter ref="contentSearch/indexConfigurations/defaultLuceneIndexConfiguration/indexFieldStorageValueFormatter"/>
<indexDocumentPropertyMapper ref="contentSearch/indexConfigurations/defaultLuceneIndexConfiguration/indexDocumentPropertyMapper"/>
</ProductIndexConfiguration>
</indexConfigurations>
</contentSearch>
</sitecore>
</configuration>
Actually a quite straightforward index that points to a root, includes a template and stores a field. It all works. But I need something extra:
Limit the entries in the index to the latest version
Limit the entries in the index to one language (English)
I know this can be easily triggered in the query as well, but I want to get my indexes smaller so they will (re)build faster.
The first one could be solved by indexing web instead of master, but I actually also want the unpublished ones in this case. I'm quite sure I will need a custom crawler for this.
The second one (limit the languages) is actually more important as I will also need this in other indexes. The easy answer is probably also to use a custom crawler but I was hoping there would be a way to configure this without custom code. Is it possible to configure an custom index to only include a defined set of languages (one or more) instead of all?
After some research I came to the conclusion that to match all the requirements a custom crawler was the only solution. Blogged the code: http://ggullentops.blogspot.be/2016/10/custom-sitecore-index-crawler.html
The main reason was that we really had to be able to set this per index - which is not possible with the filter approach. Also, when we added a new version the previous version had to be deleted from the index - also not possible without the crawler...
There is quite some code so I won't copy it all here but we had to override the DoAdd and DoUpdate methods of the SitecoreItemCrawler, and for the languages we also had to make a small override of the Update method.
You can easily create a custom processor that will let you filter what you want:
namespace Sitecore.Custom
{
public class CustomInboundIndexFilter : InboundIndexFilterProcessor
{
public override void Process(InboundIndexFilterArgs args)
{
var item = args.IndexableToIndex as SitecoreIndexableItem;
var language = Sitecore.Data.Managers.LanguageManager.GetLanguage("en");
if (item != null && (!item.Item.Versions.IsLatestVersion() || item.Item.Language == language))
{
args.IsExcluded = true;
}
}
}
}
And add this processor into the config:
<pipelines>
<indexing.filterIndex.inbound>
<processor type="Sitecore.Custom.CustomInboundIndexFilter, Sitecore.Custom"></processor>
</indexing.filterIndex.inbound>
</pipelines>

Python Debugger out of sync with code

I am in the process of debugging something in OpenERP using Python 2.7.3. The debugger seems to get out of sync with the code when stepping through with the Next (n) command. See Code and output below. I have the same problem with Python 2.6.5. I have never experienced this before using Python pdb.
I believe the problem may be related to the way OpenERP calls my method through a Python exec() statement by reading the code field in the OpenERP XML below. Is possible that calling Python code constructed dynamically and called via exec() is confusing the pdb debugger?
If this is the case is there a work around?
CODE called via this OpenERP action below:
<record id="action_wash_st_method1" model="ir.actions.server">
<field name="type">ir.actions.server</field>
<field name="condition">True</field>
<field name="state">code</field>
<field name="model_id" ref="model_view_tree_display_address_list"/>
<field eval="5" name="sequence"/>
<field name="code">
action = self.view_calc_sales_tax(cr, uid, context)
</field>
<field name="name">wash state action request</field>
</record>
<record model="ir.values" id="action_wash_st_tax_trigger_method1" >
<field name="key2" eval="'tree_but_open'" />
<field name="model" eval="'view.tree.display.address.list'" />
<field name="name">Method1 Wash State</field>
<field name="value" eval="'ir.actions.server,%d'%action_wash_st_method1"/>
<field name="object" eval="True" />
</record>

How to get Solr Suggester to return spelling suggestions as well

I'm currently integrating Apache Solr searching into my platform and using the Suggester functionality for autocompletion. However, the Suggester module does not return spelling suggestions as well, so for example if I search for:
shi
The suggester module returns among others the following:
shirt
shirts
However, if I search for:
shrt
No suggestions are returned. What I'd like to know is:
a) Is it incorrect configuration of the Suggester module that has resulted in this?
b) Is the Suggester module built in such a way that it does not return spelling suggestions?
c) How can I get the Suggester module to return spelling suggestions as well without having to make a second request for spelling correction suggestions?
I have read the Solr documentation but cannot seem to make a headway with this.
You need to configure a spell check component to generate alternate spelling options as described at https://lucene.apache.org/solr/guide/8_1/spell-checking.html
The task consists of following steps:
First, update the schema.xml with a spellcheck field. This often means creating a new field and copying multiple fields to a single spellcheck field:
<field name="spellcheck" type="text_general"
indexed="true"
stored="false"
multiValued="true"/>
<copyField source="id" dest="spellcheck"/>
<copyField source="name" dest="spellcheck"/>
<copyField source="description" dest="spellcheck"/>
<copyField source="longdescription" dest="spellcheck"/>
<copyField source="category" dest="spellcheck"/>
<copyField source="source" dest="spellcheck"/>
<copyField source="merchant" dest="spellcheck"/>
<copyField source="contact" dest="spellcheck"/>
In solrconfig.xml update your request handler and create a solr.SpellCheckComponent and add it to your search handler.
<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
<lst name="spellchecker">
<!-- decide between dictionary based vs index based spelling suggestions,
in most cases it makes sense to use index based spell checker
as it only generates terms which are
actually present in your search corpus -->
<str name="classname">solr.IndexBasedSpellChecker</str>
<!-- field to use -->
<str name="field">spellcheck</str>
<!-- buildOnCommit|buildOnOptimize -->
<str name="buildOnCommit">true</str>
<!-- $solr.solr.home/data/spellchecker-->
<str name="spellcheckIndexDir">./spellchecker</str>
<str name="accuracy">0.7</str>
<float name="thresholdTokenFrequency">.0001</float>
</lst>
</searchComponent>
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int>
<str name="df">defaultSearchField</str>
<!-- spell check component configuration -->
<str name="spellcheck">true</str>
<str name="spellcheck.count">5</str>
<str name="spellcheck.collate">true</str>
<str name="spellcheck.maxCollationTries">5</str>
</lst>
<!-- add spell check processing after
the default search component. This is
the search component name. -->
<arr name="last-components">
<str>spellcheck</str>
</arr>
</requestHandler>
Reindex the corpus
Test suggestions are working. For example,
http://localhost:8983/solr/select/?q=coachin
{
"responseHeader": {
"status": 0,
"QTime": 12,
"params": {
"indent": "true",
"q": "coachin"
}
},
"response": {
"numFound": 0,
"start": 0,
"docs": []
},
"spellcheck": {
"suggestions": [
"coachin", {
"numFound": 1,
"startOffset": 0,
"endOffset": 7,
"suggestion": ["cochin"]
}
]
}
}

Sharepoint - Custom Integer Column - Remove thousand separator in EditForm

I created a new column definition in Sharepoint 2010 of type integer and with Commas set to false.
A content type uses this column.
When I create a list based on the content type, the "View Item" form will display the field correctly: 2010.
The EditForm however will display it as 2,010: with a comma although commas is set to false.
This is a new integer field (not a number field converted to integer)
Any ideas how to display 2,010 as 2010 in the EditForm?
<Field
ID="{FF3B3FA8-AF33-4691-AD7E-1463DC024B99}"
Name="studyYear"
StaticName="studyYear"
DisplayName="Study year"
Title="Year"
Description="Study year"
Required="FALSE"
Group="Custom Columns"
Type="Integer"
Commas="FALSE"
Min="1900"
Max="2300"
MaxLength="4">
</Field>
I wanted to group list items by Year based the Created field, but needed to covert number to text to avoid 1000 separator (,)
So I created a calculated field with formula of =LEFT(YEAR(Created),1)&RIGHT(YEAR(Created),3)
I have a custom field definition that I created in SharePoint 2010.
I basically followed the pattern set forth in this MS walkthrough. - then I changed their custom 'Field' example which inherits from 'SPFieldText' to instead inherit from SPFieldNumber, and my FieldControl inherits from NumberField.
Also, here's my field definition XML:
<?xml version="1.0" encoding="utf-8" ?>
<FieldTypes>
<FieldType>
<Field Name="TypeName">Wps</Field>
<Field Name="SQLType">int</Field>
<Field Name="InternalType">Integer</Field>
<Field Name="ParentType">Number</Field>
<Field Name="TypeDisplayName">Client WPS integer</Field>
<Field Name="TypeShortDescription">Client WPS number</Field>
<Field Name="UserCreatable">TRUE</Field>
<Field Name="ShowOnListCreate">TRUE</Field>
<Field Name="ShowOnSurveyCreate">TRUE</Field>
<Field Name="ShowOnDocumentLibraryCreate">TRUE</Field>
<Field Name="ShowOnColumnTemplateCreate">TRUE</Field>
<Field Name="FieldTypeClass">MyCompany.SharePoint.WpsField, $SharePoint.Project.AssemblyFullName$</Field>
</FieldType>
</FieldTypes>
Like Karel, I had defined everything well enough that all commas were squashed.. except in the edit form.
I ended up adding some javascript to the custom .ascx that is part of my custom field definition.
<%# Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%# Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%# Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%# Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%# Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%# Import Namespace="Microsoft.SharePoint" %>
<%# Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%# Control Language="VB" %>
<SharePoint:RenderingTemplate ID="WpsFieldControl" runat="server">
<Template>
<span id="commaField">
<asp:TextBox ID="TextField" runat="server" Width="120px" />
</span>
<script type="text/javascript">// <![CDATA[
var numFld = document.getElementById("commaField").childNodes[0];
numFld.value = numFld.value.replace(",", "");
// ]]>
</script>
</Template>
</SharePoint:RenderingTemplate>
Note that I wrapped my ASP.NET TextBox in a simple SPAN with an ID that I could easily locate the field using getElementById in my JS. This was acceptable in my scenario, because the nature of our business would only ever require a single instance of my field type on a given SharePoint list record.
This seemed to solve everything for me! Maybe not the prettiest, but, I like that I don't have to clog up my list definitions with calculated columns.