如何通过Power Automate+ProjectServer REST API将Dynamics 365工时条目导入Project Online时间表?
解决Project Online REST API在Power Automate中的请求问题
问题背景
我在Dynamics 365的模型驱动应用里有个自定义Time Entry表,想自动把每条Time Entry导入用户的Project Online时间表。用Power Automate的「发送HTTP请求到SharePoint」操作调用ProjectServer REST API时碰到两个问题:
- 调用
GET _api/ProjectServer/Timesheets?$filter=PeriodId eq guid'xxx'返回404,提示"Cannot find resource for the request Timesheets",但用ODataV1端点/_api/ProjectData/TimesheetLines能正常拿数据。 - 调用
GET _api/ProjectServer/TimeSheetPeriods('xxx')/TimeSheet时,明明该周期已经手动保存了草稿工时,却一直返回{"d": {"TimeSheet": null}}。
已确认的信息:
- 站点URL是
https://<tenant>.sharepoint.com/sites/pwa(无额外路径) - 流用的是个人用户凭据
- 能通过
POST _api/contextinfo拿到有效FormDigest - 已经参考过相关示例文档
问题解答
1. 为什么/ProjectServer/Timesheets返回404但/ProjectData/TimesheetLines能用?
这是因为两个端点属于不同的API体系,且你用错了CSOM REST API的路径拼写:
/_api/ProjectServer/是基于CSOM的操作型API,而/_api/ProjectData/是OData v1的只读报表API,两者资源命名规则不同。- CSOM REST里的时间表集合正确路径是
/_api/ProjectServer/TimeSheets(注意是TimeSheets,首字母T大写,Sheets的S也大写),你原请求里的Timesheets拼写错误,直接导致了404错误。
2. 为什么TimeSheetPeriods('xxx')/TimeSheet返回null?
大概率是两个原因:
- 权限或归属问题:当前流的用户没有访问该时间表的权限,或者这个时间表根本不属于当前用户。要确保你查询的周期对应的时间表是当前用户所有,且用户有"查看自己的时间表"及以上权限。
- 端点使用逻辑错误:通过
TimeSheetPeriods关联查询时间表的方式并不靠谱,正确做法是直接针对当前用户查询时间表集合,或者用专属的当前用户端点。
Power Automate最小工作示例
示例1:获取当前用户指定周期的时间表
在「发送HTTP请求到SharePoint」里配置:
- Site Address:
https://<tenant>.sharepoint.com/sites/pwa - Method: GET
- Uri:
_api/ProjectServer/TimeSheets?$filter=PeriodId eq guid'<周期ID>' and Owner/Id eq '<当前用户ID>'&$select=Id,Owner/Id,Owner/Name,Status&$expand=Owner($select=Id,Name)
提示:当前用户ID可以用Power Automate的
User().Id动态获取;周期ID可以先调用/_api/ProjectServer/TimeSheetPeriods查询当前活跃周期拿到。
示例2:获取当前用户的所有时间表
直接用当前用户专属端点,更简洁:
- Uri:
_api/ProjectServer/Me/TimeSheets?$select=Id,PeriodId,Status,Owner/Name&$expand=Owner
示例3:把Time Entry导入Project Online时间表(创建工时条目)
要完成导入,得先拿到目标时间表ID,再添加工时线:
- 用示例1的请求获取目标时间表的ID
- 发送POST请求创建TimeSheetLine:
- Method: POST
- Uri:
_api/ProjectServer/TimeSheets('<时间表ID>')/TimeSheetLines/Add - Headers:
Content-Type:application/json;odata=verboseX-RequestDigest: 从POST _api/contextinfo返回结果里取FormDigestValue
- Body:
{ "parameters": { "Start": "2024-05-20T00:00:00", "End": "2024-05-20T23:59:59", "ProjectId": guid"<你的项目ID>", "TaskId": guid"<你的任务ID>", "Comment": "从Dynamics 365导入的工时", "ActualWork": "PT8H" } }
内容的提问来源于stack exchange,提问作者hussein
相关产品推荐
相关产品推荐

