How to format person or group field values in c#? - sharepoint-2010

I am retrieving my sharepoint list data in c# and assigning into a SPGridview.
The below is the code i am using to fill the SPGridview.
I have a column called "Contact" in my SPGridview, which is mapped to the person or group field.
After binding, when i see the "Contact" column in the SPGridview, i see the results like "Kumar, Ramesh;#55;#Kumar, Amit".
But i want the result like "Kumar, Ramesh;Kumar, Amit".
Please help me how to achieve this.
public void btnSearch_Click(object sender, EventArgs e)
{
SPList myList = SPContext.Current.Web.Lists["MyList"];
SPQuery query = new SPQuery();
query.Query = #"<Where>
<And>
<Eq>
<FieldRef Name='Year_x0020_Start' />
<Value Type='Text'>2010</Value>
</Eq>
<Eq>
<FieldRef Name='Year_x0020_End' />
<Value Type='Text'>2012</Value>
</Eq>
</And>
</Where>";
DataTable tempTbl = myList.GetItems(query).GetDataTable();
gdvSearchResults.DataSource = tempTbl;
gdvSearchResults.DataBind();
}
Thanks in advance.!

I had a similar problem but under a different circumstance. I was using the Content Query Web Part and editing a XSL template. But the same #55, etc was showing up. I got rid of it using a regular expression via JavaScript. Possibly you could do the same but on your DataTable column before it is bound to the SPGridView. The regular expression I used was:
.replace(/[;#0-9]+/g, "; ")
I blogged about it here: http://davidpopdan.blogspot.com/2012/11/using-people-picker-with-multiple-names.html
Also, if you're wondering what those numbers are, they're the user's ID, unique to the site collection you're working in. There's a hidden list that keeps track of that info.

Related

Sitecore 8 XP ContentSearch: Exclude path from Indexing

I'm having trouble with Sitecore Indexing of the general indexes "sitecore_master_index", "sitecore_web_index", which take forever because the crawler/indexer checks all items in the database.
I imported thousands of products with a whole lot of specifications and literally have hundreds of thousands of items in the product repository.
If I could exclude the path from indexing it wouldn't have to check a million items for template exclusion.
FOLLOWUP
I implemented a custom-crawler that excludes a list of paths from being indexed:
<index id="sitecore_web_index" type="Sitecore.ContentSearch.SolrProvider.SwitchOnRebuildSolrSearchIndex, Sitecore.ContentSearch.SolrProvider">
<param desc="name">$(id)</param>
<param desc="core">sitecore_web_index</param>
<param desc="rebuildcore">sitecore_web_index_sec</param>
<param desc="propertyStore" ref="contentSearch/indexConfigurations/databasePropertyStore" param1="$(id)" />
<configuration ref="contentSearch/indexConfigurations/defaultSolrIndexConfiguration" />
<strategies hint="list:AddStrategy">
<strategy ref="contentSearch/indexConfigurations/indexUpdateStrategies/onPublishEndAsync" />
</strategies>
<locations hint="list:AddCrawler">
<crawler type="Sitecore.ContentSearch.Utilities.Crawler.ExcludePathsItemCrawler, Sitecore.ContentSearch.Utilities">
<Database>web</Database>
<Root>/sitecore</Root>
<ExcludeItemsList hint="list">
<ProductRepository>/sitecore/content/Product Repository</ProductRepository>
</ExcludeItemsList>
</crawler>
</locations>
</index>
In addition I activated SwitchOnSolrRebuildIndex as it's awesome ootb functionality, cheers SC.
using System.Collections.Generic;
using System.Linq;
using Sitecore.ContentSearch;
using Sitecore.Diagnostics;
namespace Sitecore.ContentSearch.Utilities.Crawler
{
public class ExcludePathsItemCrawler : SitecoreItemCrawler
{
private readonly List<string> excludeItemsList = new List<string>();
public List<string> ExcludeItemsList
{
get
{
return excludeItemsList;
}
}
protected override bool IsExcludedFromIndex(SitecoreIndexableItem indexable, bool checkLocation = false)
{
Assert.ArgumentNotNull(indexable, "item");
if (ExcludeItemsList.Any(path => indexable.AbsolutePath.StartsWith(path)))
{
return true;
}
return base.IsExcludedFromIndex(indexable, checkLocation);
}
}
}
You can override SitecoreItemCrawler class which is used by the index you want to change:
<locations hint="list:AddCrawler">
<crawler type="Sitecore.ContentSearch.SitecoreItemCrawler, Sitecore.ContentSearch">
<Database>master</Database>
<Root>/sitecore</Root>
</crawler>
</locations>
You can then add your own parameters, e.g. ExcludeTree or even a list of ExcludedBranches.
And in the implementation of the class just override method
public override bool IsExcludedFromIndex(IIndexable indexable)
and check whether it is under excluded node.
When importing large amounts of data you should try disabling the indexing of data temporarily otherwise you'll run into issues with a crawler that can't keep up.
There's a great post here on disabling the index while importing data - it's for Lucene but I'm sure you can do the same with Solr,
http://intothecore.cassidy.dk/2010/09/disabling-lucene-indexes.html
Another option could be to store your products in a separate Sitecore database rather than in the master db.
Another post from into the core:
http://intothecore.cassidy.dk/2009/05/working-with-multiple-content-databases.html

Assign a value to an attribute of a Microsoft.TeamFoundation.Build.Common.BuildParameter object using XAML

my BuildParameter is defined in my xaml build as follows:
<Activity this:Process.AdvancedBuildSettings=
"[New Microsoft.TeamFoundation.Build.Common.BuildParameter(
" { ""Attribute1"": """",
""Attribute2"": ""Value2"",
""Attribute3"": ""Value3"" } "
)]">
Now I want to update the value of Attribute1 of my BuildParameter but I can't figure out how to do it.
It doesn't look like I can use an Assign block because these attributes names are not known by the compiler, so I want to use BuildParameter's SetValue method but I'm not sure how to call this VB code in my xaml.
<Assign DisplayName="Update That Attribute">
<Assign.To>
<OutArgument x:TypeArguments="x:String">[AdvancedBuildSettings.Attribute1]</OutArgument><!-- this throws a compiler error because it doesn't know what Attribute1 is -->
</Assign.To>
<Assign.Value>
<InArgument x:TypeArguments="x:String">""NewValue""</InArgument>
</Assign.Value>
</Assign>
Not familiar with XAML, but here is a code snippet that using TFS API in C# to update the parameter name. You can use WorkflowHelpers.DeserializeProcessParameters Method and WorkflowHelpers.SerializeProcessParameters Method to get parameter name, remove it, and add the new parameter name, maybe it can help you something:
string argumentName = "Attribute1";
var process = Microsoft.TeamFoundation.Build.Workflow.WorkflowHelpers.DeserializeProcessParameters(BuildDefinition.ProcessParameters);
if (process.ContainsKey(argumentName))
{
process.Remove(argumentName);
process.Add(argumentName, attributeValue);
BuildDefinition.ProcessParameters = WorkflowHelpers.SerializeProcessParameters(process);
BuildDefinition.Save();
}
I was right, the "Assign" workflow tool was not the tool I wanted. I needed to use the "InvokeMethod" workflow tool in order to invoke the SetValue() method of my BuildParameter object in my XAML build.
MSDN InvokeMethod documentation
More details about the properties of InvokeMethod
So my solution looks like this:
<InvokeMethod DisplayName="Invoke That Method" MethodName="SetValue">
<InvokeMethod.GenericTypeArguments>
<x:Type Type="x:String" />
</InvokeMethod.GenericTypeArguments>
<InvokeMethod.TargetObject>
<InArgument x:TypeArguments="mtbc:BuildParameter">[AdvancedBuildSettings]</InArgument>
</InvokeMethod.TargetObject>
<InArgument x:TypeArguments="x:String">Attribute1</InArgument>
<InArgument x:TypeArguments="x:String">[NewValue]</InArgument>
</InvokeMethod>

How can I use (reflection?) to make reusable code for populating object with xml data

I'm using VB.NET 2013 and am trying to write an application that will import (from csv file) customer contact information (for example: CustomerName, ContactLast, ContactFirst, ContactPhn, ContactEmail). There are going to be multiple csv layouts that have to be dealt with, so I'm using an XML file to store the various mappings in.
I'd like to load the defined maps from DataMaps.xlm into DataMap objects then insert those DataMap objects into a list box. I'd like to have them populated with the XML values before I load them into the listbox. I don't expect that there will ever be more than 10 - 15 defined maps, so loading them right away shouldn't be much of a problem with memory or speed (as it will be a locally run application with locally stored xml data).
What I have so far:
Contact Object (short and sweet for this example - not really needed at this point, but given so you can see how the data map is used)
Private mCompany as String
Private mLastName as String
Private mFirstName as String
Private mPhone as String
Private mEmail As String
<... Support Get/Set items (Properties are same as private variables; minus the leading "m") ...>
DataMap Object (short and sweet again for this example)
Private mDataMapName as String
private mCompany_Col as Integer
private mLastName_Col as Integer
private mFirstName_Col as Integer
private mPhone_Col As Integer
private mEmail_Col As String
<... Support Get/Set items (Properties are same as private variables; minus the leading "m") ...>
"Standard" CSV layout
"Company ABC", "Jones", "June", "515-874-0098", "JJ#ABC.COM"
"Company EFG", "Williams", "Alan", "515-874-2887", "alan#efg.com"
The DataMap for this layout would be:
<Map>
<DataMapName>Standard</DataMapName>
<Company>1</Company>
<LastName>2</LastName>
<FirstName>3</FirstName>
<Phone>4</Phone>
<Email>5</Email>
</Map>
"Not Standard 01" CSV Layout
"Jones", "June", "Company ABC", "515-874-0098", "JJ#ABC.COM"
"Williams", "Alan" "Company EFG", "515-874-2887", "alan#efg.com"
The DataMap for this format would be:
<Map>
<DataMapName>Not Standard 01</DataMapName>
<Company>3</Company>
<LastName>1</LastName>
<FirstName>2</FirstName>
<Phone>4</Phone>
<Email>5</Email>
</Map>
I'm just picking up VB.NET again and am not comfortable with determining the "best" techniques to use while reading data from the .xml file (I can retrieve a list of s using LINQ currently) and populating my DataMap object. I know I can do it by using each individual property to set the values; but I'd like to write generic (looping) code as this app may be rewritten with changes to the DataMap requirements as well as using this in other application instances.
Currently, I am able to create a new element and add it to the DataMaps.xml file. I can then read those changes correctly.
Where I'm stuck is writing a 'generic' populateMap(mapName As String) function. Where I am right now, I can get the map (as an Enumeration of XElement) and then individually look at each property and store it into a new instance of a DataMap object:
Dim dm as New DataMap
dm.DataMapName = map.Element("DataMapName").Value
dm.Company_Col = map.Element("Company_Col").value
dm.LastName_Col = map.Element("LastName_Col").value
dm.FirstName_Col = map.Element("FirstName_Col").value
...
But, I'd like know if it's possible to create something like: (pseudocode)
Dim dm As new DataMap
Dim myInstance As New DataMap
Dim myFields As FieldInfo()
Dim myType As Type = GetType(DataMap)
try
myFields = myType.GetFields(BindingFlags.NonPublic)
for each element in map.Elements
Dim f as FieldInfo = GETType(DataMap).GetField(field.name)
dm.(some sort of reference to a FieldInfo() column name, or something) = element.f
(this would look like: dm.Company_Col = element.Company_Col (or a variable referencing the private value "mCompany_Col")
next
catch ...
Finally ...
End Try

Get a Partial Class to show using EntityDataSource

I have an entity object student, which has properties StudentID and StudentName. I have a partial class Student which uses a service to find that student's current school. An EntityDataSource fills up the grid just fine, accept for the school. If I watch the RowDataBound event of the grid, I can watch it go to StudentModel.Designer.cs and get the StudentID and StudentName. But it does not get the school. This makes sense, because school is not part of the entity object - but, can I even get the school custom property while using an EntityDataSource?
I've been doing some research, and it seems I need to use the ContextCreating event in order to complete my object?
Before, I was adding the school during the RowDataBound event, but I want to be able to sort on school - so that is the reason I am trying to figure this out.
I'm not sure if I'm close to the solution... or this can't be done at all and I should do all my data binding in code behind?
Here is code:
<asp:EntityDataSource runat="server" ID="StudentGroupEntityDataSource"
ContextTypeName="GearUp.Data.StudentGroupEntities" OnContextCreating="StudentGroupEntityDataSource_ContextCreating" OnContextCreated="StudentGroupEntityDataSource_ContextCreated"
EnableFlattening="False" EnableDelete="True" EnableInsert="True" EnableUpdate="True"
EntitySetName="StudentGroupMembers"
OrderBy="it.FullName"
Where="it.GroupID IN {#ID}">
<WhereParameters>
<asp:ControlParameter DbType="Guid" Name="ID" ControlID="StudentGroupDropDown"
PropertyName="SelectedValue" />
</WhereParameters>
</asp:EntityDataSource>
public partial class StudentGroupMember
{
private string _school;
public string School
{
get
{
if (_school == null)
{
StudentServiceClient clientStudent = new StudentServiceClient();
var studentDetail = clientStudent.RetrieveStudentDetail(this.StudentID.ToString());
_school = studentDetail.SchoolName;
}
return _school;
}
}
}

JSTL tag for accessing an arraylist so that it can be filled in a list box

I have seen two questions relating to my topic on stackoverflow, but those answers did not work for me, hence this question. I have the following object
public class CartProduct {
private ArrayList<String> accList = new ArrayList<String>();
public void setAccList(ArrayList<String> str)
{
this.accList = str;
}
public ArrayList<String> getAccList()
{
return accList;
}
I am using the following code to access this list and then its individual items using JSTL so that they can populate a list box in a JSP. But this code is not working and I dont seem to understand why?
<td><select name = "acc_no">
<Option value = "select">SELECT</Option>
<c:forEach items="${item.product.accList}" var="acno">
<option>${acno}</option>
</c:forEach>
</select>
The list box is empty except for the SELECT word.
The JSTL code looks fine. The JSP page is simply not accessing the instance you think it is accessing.
Check how you are sending the Customer class in the jsp page and check if the accList is empty or not?