How do I extract the type from a field?
Asked Answered
W

4

7

In SharePoint Server side code, you can write something like:

field.fieldvalueType

Which will sometimes give you the type (DateTime, or whatever). Annoyingly, sometimes, it just returns Null (for example, the ID field).

In CSOM, you don't have that field. However, there's TypeAsString which gives SharePoint types such as:

  • Computed
  • Integer
  • Note

What I'd like to do is grab this huge table from MSDN:

And Extract "Int32" when I know that I'm dealing with an "Integer" field, and extract "System.String" from SharePoint's note.

This kinda works, but it's the mother of all hacks:

var myTempItem = list.AddItem(new ListItemCreationInformation());
myTempItem.Update();
context.ExecuteQuery();

context.Load(myTempItem);
context.ExecuteQuery();

After creation, you can use:

myTempItemCreated[fieldImTryingToGetTypeOf.Title].GetType().FullName -> Gives-> System.Int32

Now, what's the proper way to do it? I'm just hoping the answer isn't a ten foot long switch case statement.

Wifeless answered 11/9, 2015 at 11:27 Comment(0)
N
3

Since there is no SPField.FieldValueType property counterparts in SharePoint CSOM API, the following extension method demonstrates how to perform it:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SharePoint.Client;
using Field = Microsoft.SharePoint.Client.Field;

namespace SharePoint.Client.Extensions
{
    public static class FieldExtensions
    {


        public static Type GetFieldValueType(this Field field)
        {
            var table = new Dictionary<FieldType, Type>();
            table[FieldType.Guid] = typeof(Guid);
            table[FieldType.Attachments] = typeof(bool);
            table[FieldType.Boolean] = typeof(bool);
            table[FieldType.Choice] = typeof (string);
            table[FieldType.CrossProjectLink] = typeof(bool);
            table[FieldType.DateTime] = typeof(DateTime);
            table[FieldType.Lookup] = typeof(FieldLookupValue);
            table[FieldType.ModStat] = typeof(int);
            table[FieldType.MultiChoice] = typeof(string[]);
            table[FieldType.Number] = typeof(double);
            table[FieldType.Recurrence] = typeof(bool);
            table[FieldType.Text] = typeof(string);
            table[FieldType.URL] = typeof(FieldUrlValue);
            table[FieldType.URL] = typeof(FieldUrlValue);
            table[FieldType.User] = typeof(FieldUserValue);
            table[FieldType.WorkflowStatus] = typeof(int);
            table[FieldType.ContentTypeId] = typeof(ContentTypeId);
            table[FieldType.Note] = typeof(string);
            table[FieldType.Counter] = typeof(int);
            table[FieldType.Computed] = typeof(string);
            table[FieldType.Integer] = typeof(int);
            table[FieldType.File] = typeof(string);

            if (!table.ContainsKey(field.FieldTypeKind))
                throw new NotSupportedException(string.Format("Unknown field type: {0}", field.FieldTypeKind));
            return table[field.FieldTypeKind];
        }
    }
}

Usage

var list = ctx.Web.Lists.GetByTitle(listTitle);
var fields = list.Fields;
ctx.Load(fields);
ctx.ExecuteQuery();

foreach (var field in fields)
{
    if (field.FieldTypeKind != FieldType.Invalid)
    {
         var fieldValueType = field.GetFieldValueType();
         Console.WriteLine("{0} : {1}", field.InternalName, fieldValueType);    
    }        
}
Noachian answered 21/9, 2015 at 10:38 Comment(2)
I guess, sometimes, there simply is no lazy way out. quote2day.com/wp-content/uploads/Photo-35.jpgWifeless
:) i also consider myself a lazy person, but in this particular case it seems to be the only way..Noachian
A
1

Expanding on @Vadim's answer, here is a version that does not construct a new dictionary every time the extension method is called;

namespace SharePoint.Client.Extensions
{
    public static class FieldExtensions
    {
        private static Dictionary<FieldType, Type> _fieldTypes = new Dictionary<FieldType, Type>()
        {
            { FieldType.Guid, typeof(Guid) },
            { FieldType.Attachments, typeof(bool)},
            {FieldType.Boolean, typeof(bool)},
            {FieldType.Choice, typeof(string)},
            {FieldType.CrossProjectLink, typeof(bool)},
            {FieldType.DateTime, typeof(DateTime)},
            {FieldType.Lookup, typeof(FieldLookupValue)},
            {FieldType.ModStat, typeof(int)},
            {FieldType.MultiChoice, typeof(string[])},
            {FieldType.Number, typeof(double)},
            {FieldType.Recurrence, typeof(bool)},
            {FieldType.Text, typeof(string)},
            {FieldType.URL, typeof(FieldUrlValue)},
            {FieldType.User, typeof(FieldUserValue)},
            {FieldType.WorkflowStatus, typeof(int)},
            {FieldType.ContentTypeId, typeof(ContentTypeId)},
            {FieldType.Note, typeof(string)},
            {FieldType.Counter, typeof(int)},
            {FieldType.Computed, typeof(string)},
            {FieldType.Integer, typeof(int)},
            {FieldType.File, typeof(string)}
        };

        public static Type GetFieldValueType(this Field field)
        {
            if (!_fieldTypes.ContainsKey(field.FieldTypeKind))
                throw new NotSupportedException(string.Format("Unknown field type: {0}", field.FieldTypeKind));
            return _fieldTypes[field.FieldTypeKind];
        }
    }
}
Arellano answered 10/4, 2017 at 16:25 Comment(0)
R
0

Generally, you need to do the mapping you describe, not the myTempItemCreated[fieldImTryingToGetTypeOf.Title].GetType().FullName method.

The reason is, myTempItemCreated[fieldImTryingToGetTypeOf.Title].GetType().FullName will fail in the scenario where the field value (e.g. Title) is null for that particular ListItem object. (While Title is not generally null, other fields can be and are null). And obviously null does not give you an object on which you can call the GetType() method (you would get a NullReferenceException obviously).

So, for a general solution to the problem, one does indeed have to map the String returned from TypeAsString of the list field, calling from the list object / list field, and not from the list item.

Randy answered 19/9, 2015 at 13:18 Comment(0)
B
-1

You can get the type of field using the following snippet:

item.Fields["Title"].FieldValueType.FullName
Benzel answered 14/9, 2015 at 12:46 Comment(2)
Sorry i'm confused as to what's required? Do you wish to get the value of the field? i,e: Just call a method to get the value and it returns the value based on it's type?Benzel
Sorry but the question is pretty clear. Your answer is literally the second line of the question (which is obviously really frustrating). I need to get the type of the field without creating a list item. Read the question as to an explanation of why your snippet does not work.Wifeless

© 2022 - 2024 — McMap. All rights reserved.