简体   繁体   中英

SharePoint CAML Query - How to read MetaInfo field values programmatically?

I am using C# and SharePoint Client Object Model to query recursively across folders to get file properties in the collection returned.

I successfully can read the value from the ListItemCollection by specifying the field name like this:

listItem["Title"] 

but is there a way to read the individual values in

listItem["MetaInfo"]

which appears to have multiple custom meta data values, I suppose set by Microsoft office applications??? Can I cast it to a type to get the individual values?

I do not want to be parsing the string....

The data in the debugger for the MetaInfo feild looks like this:

display_urn\\:schemas-microsoft-com\\:office\\:office#Editor:SW|System Account
   \nvti_parserversion:SR|14.0.0.7149
   \nvti_folderitemcount:IR|0
   ContentTypeId:SW|0x0101008B5F2095338FE647A7F89B5275681D66
   vti_title:SW|Mr Foo Howe 26-03-2014
   vti_author:SW|MYDOMAIN\\\\jblogs
   Document Type:SW|Contract Note
   vti_modifiedby:SR|SHAREPOINT\\\\system
   vti_foldersubfolderitemcount:IR|0
   display_urn\\:schemas-microsoft-com\\:office\\:office#Author:SW|Blogs, Jo

Thank for your help and please excuse my ignorance - it is the first time I am dealing with SharePoint :)

SharePoint CSOM API does not contain builtin method for parsing MetaInfo field value which returns string representation of metadata information that is associated with the specified client object.

You could consider the below method for parsing MetaInfo field value:

/// <summary>
/// Parse MetaInfo field value
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private static Dictionary<string, string> ParseMetaInfo(string value)
{
    return value.Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
            .Select(x => x.Split(new[] {":"}, StringSplitOptions.RemoveEmptyEntries))
            .ToDictionary(x => x[0], x => x[1]);
}

Usage

var list = ctx.Web.Lists.GetByTitle(targetListTitle);
var items = list.GetItems(CamlQuery.CreateAllItemsQuery());
ctx.Load(items, icol => icol.Include( i => i["MetaInfo"]));
//ctx.Load(items);
ctx.ExecuteQuery();

foreach (var item in items)
{
    var metaInfo = (string) item["MetaInfo"];
    var metaInfoValue = ParseMetaInfo(metaInfo);
    //..

}

I have marked Vadim's solution as an answer however I thought I'll post my solution, which I did before I saw his response.

The implementation below is using Extension methods and Regular Expression Match to extract the values - it is useful if you already know the fields you will be reading ie they are predefined - if you do not know what you'll be dealing with and they are dynamic then the answer above may be more useful to you.

Extension methods and class defining the meta info properties in the MetaInfo field you may need to retrieve:

public static class Extensions
{

    public static string[] DocMetaInfoFields =
    {
        MetaInfoFields.Title, MetaInfoFields.Author,
        MetaInfoFields.DocumentType, MetaInfoFields.ModifiedBy
    };

    public static string GetDocumentType(this object metaInfo)
    {
        var match = GetRegexMatch(metaInfo as string, MetaInfoFields.DocumentType);
        return (match.Groups.Count > 1)
            ? match.Groups[1].Value
            : string.Empty;
    }

    public static Dictionary<string, string> GetDocMetaProperties(this object metaInfo)
    {
        var properties = new Dictionary<string, string>();
        foreach (var field in DocMetaInfoFields)
        {
            var match = GetRegexMatch(metaInfo as string, field);
            properties.Add(field,
                (match.Groups.Count > 1)
                    ? match.Groups[1].Value
                    : string.Empty);
        }
        return properties;
    }

    public static StringBuilder FormatCamlValues(this StringBuilder sb, string valueTag, string listName,
        IEnumerable<string> clientReferences)
    {
        foreach (var clientRef in clientReferences)
        {
            sb.AppendFormat(valueTag, listName, clientRef);
        }
        return sb;
    }

    public static List<ClientDocumentListItem> ToClientDocumentList(this ListItemCollection files)
    {
        return files.ToList().ConvertAll(ListItemToClientDocItem);
    }

    private static Match GetRegexMatch(string searchString, string fieldName)
    {
        string regexCapture = string.Format(@"^{0}:\w{{2}}\|([^.(\r|\n)]*)[\r\n|\n\r]+\w", fieldName);
        return Regex.Match(searchString, regexCapture, RegexOptions.Multiline);
    }
}

/// <summary>
/// Defines the field names inside the MetaInfo composite field returned while using the SharePoint client object CamlQuery() method
/// </summary>
public static class MetaInfoFields
{
    public static string MetaInfoFieldName = "MetaInfo";
    public static string Title = "vti_title";
    public static string Author = "vti_author";
    public static string DocumentType = "Document Type";
    public static string ModifiedBy = "vti_modifiedby";
}

Usage

var list = ctx.Web.Lists.GetByTitle(targetListTitle);
var items = list.GetItems(CamlQuery.CreateAllItemsQuery());
ctx.Load(items, icol => icol.Include( i => i[MetaInfoFields.MetaInfoFieldName]));
//ctx.Load(items);
ctx.ExecuteQuery();

var docProperties = GetDocMetaProperties(listItem[MetaInfoFields.MetaInfoFieldName]);

var title = docProperties[MetaInfoFields.Title];    
var createdBy = docProperties[MetaInfoFields.Author];    
var modifiedBy = docProperties[MetaInfoFields.ModifiedBy];    
var type = docProperties[MetaInfoFields.DocumentType];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM