创建和修改的文件对象 属性 值不同于 ListItemCollection 和 FileCollection
File object created and modified property values vary from ListItemCollection and FileCollection
我注意到在从 ListItemCollection 和 FileCollection 调用 File obj Created 和 Modified 属性时值存在一些差异。详情如下:
下面是一些旧代码,它从我初始化所需属性的 FileCollection 中的文件夹中获取文件:
using (var spClientContext = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, _clientId, _clientSecret))
{
if (spClientContext != null)
{
List list = spClientContext.Web.Lists.GetByTitle("Documents");
spClientContext.Load(list);
spClientContext.Load(list.RootFolder);
spClientContext.Load(list.RootFolder.Folders);
spClientContext.ExecuteQuery();
FolderCollection fcol = list.RootFolder.Folders;
if (fcol != null)
{
foreach (Folder f in fcol)
{
if (f.Name.Equals(folderName, StringComparison.InvariantCultureIgnoreCase))
{
spClientContext.Load(f.Files,
items => items.Include(
item => item.Name,
item => item.Author,
item => item.ModifiedBy,
item => item.ListItemAllFields["Created"],
item => item.ListItemAllFields["Modified"],
item => item.ListItemAllFields["FileRef"],
item => item.Length));
spClientContext.ExecuteQuery();
FileCollection fileCol = f.Files;
foreach (File file in fileCol)
{
// Do Stuff
}
}
}
}
}
}
当我输出文件创建和修改的 date/time 值时,我得到以下信息:
- 创建时间:6/17/2021 11:40:28 下午(正确 Date/Time)
- 修改时间:6/17/2021 11:41:12 下午(正确 Date/Time)
下面是我更新的代码,它在 ListItemCollection 中收集文件并初始化文件属性:
using (ClientContext spClientContext = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, _clientId, _clientSecret))
{
if (spClientContext != null)
{
CamlQuery camlQuery = new CamlQuery();
camlQuery.FolderServerRelativeUrl = getSiteUrlAbsolutePath(siteUrl) + "/Shared Documents/" + folderPath;
camlQuery.ViewXml = "<View Scope="RecursiveAll">" +
"<Query>" +
"<Where>" +
"<Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>0</Value></Eq>" +
"</Where>" +
"</Query>" +
"</View>";
List list = spClientContext.Web.Lists.GetByTitle("Documents");
ListItemCollection listItems = list.GetItems(camlQuery);
spClientContext.Load(listItems,
items => items.Include(
item => item.DisplayName,
item => item.FileSystemObjectType,
item => item.File,
item => item.File.Name,
item => item.File.Author,
item => item.File.ModifiedBy,
item => item.File.ListItemAllFields["Created"],
item => item.File.ListItemAllFields["Modified"],
item => item.File.ListItemAllFields["FileRef"],
item => item.File.Length));
spClientContext.ExecuteQuery();
if (listItems != null && listItems.Count > 0)
{
foreach (ListItem item in listItems)
{
if (item.FileSystemObjectType.Equals(FileSystemObjectType.File))
{
// Do Stuff
}
}
}
}
}
当我输出文件创建和修改的 date/time 值时,我得到以下信息:
- 创建时间:6/18/2021 6:40:28 上午(不正确 Date/Time)
- 修改时间:6/18/2021 6:41:12 上午(不正确 Date/Time)
新代码中的所有其他文件属性似乎都是正确的。据我所知,新代码 Created 和 Modified 正在输出 UTC 并且不识别 SharePoint 站点设置中的时区设置?还是我在错误的位置初始化了文件属性?
感谢任何反馈和帮助!
编辑:
正在加载@Antonio Leonardo 建议的带有区域站点设置的以下代码:
using (ClientContext spClientContext = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, _clientId, _clientSecret))
{
if (spClientContext != null)
{
Web web = spClientContext.Web;
spClientContext.Load(web.RegionalSettings);
spClientContext.ExecuteQuery();
int localId = (int)web.RegionalSettings.LocaleId;
string cultureInfo = (new CultureInfo(localId)).Name;
System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(cultureInfo);
CamlQuery camlQuery = new CamlQuery();
camlQuery.FolderServerRelativeUrl = getSiteUrlAbsolutePath(siteUrl) + "/Shared Documents/" + folderPath;
camlQuery.ViewXml = "<View Scope="RecursiveAll">" +
"<Query>" +
"<Where>" +
"<Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>0</Value></Eq>" +
"</Where>" +
"</Query>" +
"</View>";
List list = spClientContext.Web.Lists.GetByTitle("Documents");
ListItemCollection listItems = list.GetItems(camlQuery);
spClientContext.Load(listItems,
items => items.Include(
item => item.DisplayName,
item => item.FileSystemObjectType,
item => item.File,
item => item.File.Name,
item => item.File.Author,
item => item.File.ModifiedBy,
item => item.File.ListItemAllFields["Created"],
item => item.File.ListItemAllFields["Modified"],
item => item.File.ListItemAllFields["FileRef"],
item => item.File.Length));
spClientContext.ExecuteQuery();
if (listItems != null && listItems.Count > 0)
{
foreach (ListItem item in listItems)
{
if (item.FileSystemObjectType.Equals(FileSystemObjectType.File))
{
// Do Stuff
}
}
}
}
}
当我输出加载了区域站点设置的文件创建和修改 date/time 值时,我得到以下信息:
- 创建时间:6/18/2021 6:40:28 上午(不正确 Date/Time)
- 修改时间:6/18/2021 6:41:12 上午(不正确 Date/Time)
对您的代码进行简短分析,我同意您假设第二种方法需要识别 SharePoint 网站集中定义的时区;然后我建议测试下面的代码以尝试更改输出。下面的代码将捕获区域设置,这将在运行时设置您的应用程序文化信息(这需要在日期捕获之前添加):
Web web = spClientContext.Web;
spClientContext.Load(web.RegionalSettings);
spClientContext.ExecuteQuery();
int localId = (int) web.RegionalSettings.LocaleId;
string cultureInfo = (new CultureInfo(localId)).Name;
System.Threading.Thread.CurrentThread.CurrentUICulture =
CultureInfo.GetCultureInfo(cultureInfo);
但是,经过测试,你上面分享的这个方法并没有纠正日期错误。
在研究中,我在这个 SharePoint Stack Exchange 主题(SharePoint DateTime conversion issue in ASP.NET,状态已解决)中遇到了同样的问题,其中包含另一种修复日期输出的方法;请检查它是否适合您的情况:
SPRegionalSettings regionalSettings = web.RegionalSettings;
SPTimeZone timeZone = regionalSettings.TimeZone;
timeZone.UTCToLocalTime(dateTimeObject);
为我原来的问题找到了可靠的解决方案。下面是我正在使用的 ConvertUTCToLocalDateTime() 方法的副本。我通过它传递所有 SharePoint DateTime 属性并检查 DateTime 是 UTC 还是本地。如果 UTC 使用站点时区区域设置转换为本地。这省去了试图找出哪些属性是 UTC 或 Local 的痛苦,因为它们不同于 属性:
// File object DateTime ListItemAllFields property example calling ConvertUTCToLocalDateTime()
DateTime fileCreated = File.IsObjectPropertyInstantiated("ListItemAllFields") ?
ConvertUTCToLocalDateTime(spClientContext, (DateTime)File.ListItemAllFields["Created"]) : default(DateTime);
.
.
.
// FileVersion object DateTime property example calling ConvertUTCToLocalDateTime()
DateTime versionModified = FileVersion.IsPropertyAvailable("Created") ?
ConvertUTCToLocalDateTime(spClientContext, FileVersion.Created) : default(DateTime);
.
.
.
/// <summary>
/// Converts SharePoint UTC DateTime to Local DateTime using site regional time zone settings.
/// </summary>
/// <remarks>
/// SharePoint DateTime values can be a mix of UTC and Local in API. Need to pass all DateTime values through this method to check.
/// </remarks>
/// <param name="spClientContext">ClientContext</param>
/// <param name="dateObj">DateTime</param>
/// <returns>DateTime</returns>
public static DateTime ConvertUTCToLocalDateTime(ClientContext spClientContext, DateTime dateObj)
{
try
{
if (spClientContext != null)
{
DateTime temp;
if (DateTime.TryParse(dateObj.ToString(), out temp))
{
if (dateObj.Kind == DateTimeKind.Utc)
{
// convert utc datetime to local datetime using sharepoint site regional time zone settings
Microsoft.SharePoint.Client.TimeZone sharePointTimeZone = spClientContext.Web.RegionalSettings.TimeZone;
ClientResult<DateTime> localDateTime = sharePointTimeZone.UTCToLocalTime(dateObj);
spClientContext.ExecuteQuery();
return localDateTime.Value;
}
else if (dateObj.Kind == DateTimeKind.Local)
{
// local datetime just return (no convertion required)
return dateObj;
}
else if(dateObj.Kind == DateTimeKind.Unspecified)
{
// unspecified datetime handle as required
return dateObj;
}
}
}
}
catch (Exception ex)
{
// log exception
}
return dateObj;
}
此外,如果您使用 CamlQuery 获取 ListItemCollection 列表项,作为替代(或额外措施),您可以将 CamlQuery.DatesInUtc 属性 设置为 False,这将 return 所有初始化属性的本地 DateTime 值:
using (ClientContext spClientContext = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, _clientId, _clientSecret))
{
if (spClientContext != null)
{
Web web = spClientContext.Web;
spClientContext.Load(web.RegionalSettings);
spClientContext.ExecuteQuery();
int localId = (int)web.RegionalSettings.LocaleId;
string cultureInfo = (new CultureInfo(localId)).Name;
System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(cultureInfo);
CamlQuery camlQuery = new CamlQuery();
camlQuery.DatesInUtc = false; // uses site regional time zone datetime when set to false
camlQuery.FolderServerRelativeUrl = getSiteUrlAbsolutePath(siteUrl) + "/Shared Documents/" + folderPath;
camlQuery.ViewXml = "<View Scope="RecursiveAll">" +
"<Query>" +
"<Where>" +
"<Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>0</Value></Eq>" +
"</Where>" +
"</Query>" +
"</View>";
List list = spClientContext.Web.Lists.GetByTitle("Documents");
ListItemCollection listItems = list.GetItems(camlQuery);
spClientContext.Load(listItems,
items => items.Include(
item => item.DisplayName,
item => item.FileSystemObjectType,
item => item.File,
item => item.File.Name,
item => item.File.Author,
item => item.File.ModifiedBy,
item => item.File.ListItemAllFields["Created"],
item => item.File.ListItemAllFields["Modified"],
item => item.File.ListItemAllFields["FileRef"],
item => item.File.Length));
spClientContext.ExecuteQuery();
if (listItems != null && listItems.Count > 0)
{
foreach (ListItem item in listItems)
{
if (item.FileSystemObjectType.Equals(FileSystemObjectType.File))
{
// Do Stuff
}
}
}
}
}
希望这些解决方案对您有所帮助,因为关于此事的官方文档不多。感谢您对 post!
的所有反馈
我注意到在从 ListItemCollection 和 FileCollection 调用 File obj Created 和 Modified 属性时值存在一些差异。详情如下:
下面是一些旧代码,它从我初始化所需属性的 FileCollection 中的文件夹中获取文件:
using (var spClientContext = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, _clientId, _clientSecret))
{
if (spClientContext != null)
{
List list = spClientContext.Web.Lists.GetByTitle("Documents");
spClientContext.Load(list);
spClientContext.Load(list.RootFolder);
spClientContext.Load(list.RootFolder.Folders);
spClientContext.ExecuteQuery();
FolderCollection fcol = list.RootFolder.Folders;
if (fcol != null)
{
foreach (Folder f in fcol)
{
if (f.Name.Equals(folderName, StringComparison.InvariantCultureIgnoreCase))
{
spClientContext.Load(f.Files,
items => items.Include(
item => item.Name,
item => item.Author,
item => item.ModifiedBy,
item => item.ListItemAllFields["Created"],
item => item.ListItemAllFields["Modified"],
item => item.ListItemAllFields["FileRef"],
item => item.Length));
spClientContext.ExecuteQuery();
FileCollection fileCol = f.Files;
foreach (File file in fileCol)
{
// Do Stuff
}
}
}
}
}
}
当我输出文件创建和修改的 date/time 值时,我得到以下信息:
- 创建时间:6/17/2021 11:40:28 下午(正确 Date/Time)
- 修改时间:6/17/2021 11:41:12 下午(正确 Date/Time)
下面是我更新的代码,它在 ListItemCollection 中收集文件并初始化文件属性:
using (ClientContext spClientContext = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, _clientId, _clientSecret))
{
if (spClientContext != null)
{
CamlQuery camlQuery = new CamlQuery();
camlQuery.FolderServerRelativeUrl = getSiteUrlAbsolutePath(siteUrl) + "/Shared Documents/" + folderPath;
camlQuery.ViewXml = "<View Scope="RecursiveAll">" +
"<Query>" +
"<Where>" +
"<Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>0</Value></Eq>" +
"</Where>" +
"</Query>" +
"</View>";
List list = spClientContext.Web.Lists.GetByTitle("Documents");
ListItemCollection listItems = list.GetItems(camlQuery);
spClientContext.Load(listItems,
items => items.Include(
item => item.DisplayName,
item => item.FileSystemObjectType,
item => item.File,
item => item.File.Name,
item => item.File.Author,
item => item.File.ModifiedBy,
item => item.File.ListItemAllFields["Created"],
item => item.File.ListItemAllFields["Modified"],
item => item.File.ListItemAllFields["FileRef"],
item => item.File.Length));
spClientContext.ExecuteQuery();
if (listItems != null && listItems.Count > 0)
{
foreach (ListItem item in listItems)
{
if (item.FileSystemObjectType.Equals(FileSystemObjectType.File))
{
// Do Stuff
}
}
}
}
}
当我输出文件创建和修改的 date/time 值时,我得到以下信息:
- 创建时间:6/18/2021 6:40:28 上午(不正确 Date/Time)
- 修改时间:6/18/2021 6:41:12 上午(不正确 Date/Time)
新代码中的所有其他文件属性似乎都是正确的。据我所知,新代码 Created 和 Modified 正在输出 UTC 并且不识别 SharePoint 站点设置中的时区设置?还是我在错误的位置初始化了文件属性?
感谢任何反馈和帮助!
编辑:
正在加载@Antonio Leonardo 建议的带有区域站点设置的以下代码:
using (ClientContext spClientContext = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, _clientId, _clientSecret))
{
if (spClientContext != null)
{
Web web = spClientContext.Web;
spClientContext.Load(web.RegionalSettings);
spClientContext.ExecuteQuery();
int localId = (int)web.RegionalSettings.LocaleId;
string cultureInfo = (new CultureInfo(localId)).Name;
System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(cultureInfo);
CamlQuery camlQuery = new CamlQuery();
camlQuery.FolderServerRelativeUrl = getSiteUrlAbsolutePath(siteUrl) + "/Shared Documents/" + folderPath;
camlQuery.ViewXml = "<View Scope="RecursiveAll">" +
"<Query>" +
"<Where>" +
"<Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>0</Value></Eq>" +
"</Where>" +
"</Query>" +
"</View>";
List list = spClientContext.Web.Lists.GetByTitle("Documents");
ListItemCollection listItems = list.GetItems(camlQuery);
spClientContext.Load(listItems,
items => items.Include(
item => item.DisplayName,
item => item.FileSystemObjectType,
item => item.File,
item => item.File.Name,
item => item.File.Author,
item => item.File.ModifiedBy,
item => item.File.ListItemAllFields["Created"],
item => item.File.ListItemAllFields["Modified"],
item => item.File.ListItemAllFields["FileRef"],
item => item.File.Length));
spClientContext.ExecuteQuery();
if (listItems != null && listItems.Count > 0)
{
foreach (ListItem item in listItems)
{
if (item.FileSystemObjectType.Equals(FileSystemObjectType.File))
{
// Do Stuff
}
}
}
}
}
当我输出加载了区域站点设置的文件创建和修改 date/time 值时,我得到以下信息:
- 创建时间:6/18/2021 6:40:28 上午(不正确 Date/Time)
- 修改时间:6/18/2021 6:41:12 上午(不正确 Date/Time)
对您的代码进行简短分析,我同意您假设第二种方法需要识别 SharePoint 网站集中定义的时区;然后我建议测试下面的代码以尝试更改输出。下面的代码将捕获区域设置,这将在运行时设置您的应用程序文化信息(这需要在日期捕获之前添加):
Web web = spClientContext.Web;
spClientContext.Load(web.RegionalSettings);
spClientContext.ExecuteQuery();
int localId = (int) web.RegionalSettings.LocaleId;
string cultureInfo = (new CultureInfo(localId)).Name;
System.Threading.Thread.CurrentThread.CurrentUICulture =
CultureInfo.GetCultureInfo(cultureInfo);
但是,经过测试,你上面分享的这个方法并没有纠正日期错误。
在研究中,我在这个 SharePoint Stack Exchange 主题(SharePoint DateTime conversion issue in ASP.NET,状态已解决)中遇到了同样的问题,其中包含另一种修复日期输出的方法;请检查它是否适合您的情况:
SPRegionalSettings regionalSettings = web.RegionalSettings;
SPTimeZone timeZone = regionalSettings.TimeZone;
timeZone.UTCToLocalTime(dateTimeObject);
为我原来的问题找到了可靠的解决方案。下面是我正在使用的 ConvertUTCToLocalDateTime() 方法的副本。我通过它传递所有 SharePoint DateTime 属性并检查 DateTime 是 UTC 还是本地。如果 UTC 使用站点时区区域设置转换为本地。这省去了试图找出哪些属性是 UTC 或 Local 的痛苦,因为它们不同于 属性:
// File object DateTime ListItemAllFields property example calling ConvertUTCToLocalDateTime()
DateTime fileCreated = File.IsObjectPropertyInstantiated("ListItemAllFields") ?
ConvertUTCToLocalDateTime(spClientContext, (DateTime)File.ListItemAllFields["Created"]) : default(DateTime);
.
.
.
// FileVersion object DateTime property example calling ConvertUTCToLocalDateTime()
DateTime versionModified = FileVersion.IsPropertyAvailable("Created") ?
ConvertUTCToLocalDateTime(spClientContext, FileVersion.Created) : default(DateTime);
.
.
.
/// <summary>
/// Converts SharePoint UTC DateTime to Local DateTime using site regional time zone settings.
/// </summary>
/// <remarks>
/// SharePoint DateTime values can be a mix of UTC and Local in API. Need to pass all DateTime values through this method to check.
/// </remarks>
/// <param name="spClientContext">ClientContext</param>
/// <param name="dateObj">DateTime</param>
/// <returns>DateTime</returns>
public static DateTime ConvertUTCToLocalDateTime(ClientContext spClientContext, DateTime dateObj)
{
try
{
if (spClientContext != null)
{
DateTime temp;
if (DateTime.TryParse(dateObj.ToString(), out temp))
{
if (dateObj.Kind == DateTimeKind.Utc)
{
// convert utc datetime to local datetime using sharepoint site regional time zone settings
Microsoft.SharePoint.Client.TimeZone sharePointTimeZone = spClientContext.Web.RegionalSettings.TimeZone;
ClientResult<DateTime> localDateTime = sharePointTimeZone.UTCToLocalTime(dateObj);
spClientContext.ExecuteQuery();
return localDateTime.Value;
}
else if (dateObj.Kind == DateTimeKind.Local)
{
// local datetime just return (no convertion required)
return dateObj;
}
else if(dateObj.Kind == DateTimeKind.Unspecified)
{
// unspecified datetime handle as required
return dateObj;
}
}
}
}
catch (Exception ex)
{
// log exception
}
return dateObj;
}
此外,如果您使用 CamlQuery 获取 ListItemCollection 列表项,作为替代(或额外措施),您可以将 CamlQuery.DatesInUtc 属性 设置为 False,这将 return 所有初始化属性的本地 DateTime 值:
using (ClientContext spClientContext = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, _clientId, _clientSecret))
{
if (spClientContext != null)
{
Web web = spClientContext.Web;
spClientContext.Load(web.RegionalSettings);
spClientContext.ExecuteQuery();
int localId = (int)web.RegionalSettings.LocaleId;
string cultureInfo = (new CultureInfo(localId)).Name;
System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(cultureInfo);
CamlQuery camlQuery = new CamlQuery();
camlQuery.DatesInUtc = false; // uses site regional time zone datetime when set to false
camlQuery.FolderServerRelativeUrl = getSiteUrlAbsolutePath(siteUrl) + "/Shared Documents/" + folderPath;
camlQuery.ViewXml = "<View Scope="RecursiveAll">" +
"<Query>" +
"<Where>" +
"<Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>0</Value></Eq>" +
"</Where>" +
"</Query>" +
"</View>";
List list = spClientContext.Web.Lists.GetByTitle("Documents");
ListItemCollection listItems = list.GetItems(camlQuery);
spClientContext.Load(listItems,
items => items.Include(
item => item.DisplayName,
item => item.FileSystemObjectType,
item => item.File,
item => item.File.Name,
item => item.File.Author,
item => item.File.ModifiedBy,
item => item.File.ListItemAllFields["Created"],
item => item.File.ListItemAllFields["Modified"],
item => item.File.ListItemAllFields["FileRef"],
item => item.File.Length));
spClientContext.ExecuteQuery();
if (listItems != null && listItems.Count > 0)
{
foreach (ListItem item in listItems)
{
if (item.FileSystemObjectType.Equals(FileSystemObjectType.File))
{
// Do Stuff
}
}
}
}
}
希望这些解决方案对您有所帮助,因为关于此事的官方文档不多。感谢您对 post!
的所有反馈