Project Browsing
The base URI schema of ACC Issue API is: https://developer.api.autodesk.com/construction/issues/v1/projects/:projectId
, where the projectId is a required URI parameter. In this step we'll extend the server to browse the projects of Autodesk Construction Cloud, in order to fetch project Id.
We will basically get the hierarchy of hubs and projects using Data Management APIs.
Browsing hubs
We will add a couple of helper methods for browsing through the hubs, projects:
- Node.js & VSCode
- .NET & VSCode
- .NET & VS2022
Let's implement the logic for browsing through the individual hubs, projects.
First, let's include the Data Management SDK, add the @aps_sdk/data-management
library, and also create an instance of
SDK client of DataManagementClient
at the beginning of services/aps.js
file:
const { SdkManagerBuilder } = require('@aps_sdk/autodesk-sdkmanager');
const { AuthenticationClient, Scopes, ResponseType } = require('@aps_sdk/authentication');
const { DataManagementClient } = require('@aps_sdk/data-management');
const { APS_CLIENT_ID, APS_CLIENT_SECRET, APS_CALLBACK_URL, INTERNAL_TOKEN_SCOPES, PUBLIC_TOKEN_SCOPES } = require('../config.js');
const service = module.exports = {};
const sdk = SdkManagerBuilder.create().build();
const authenticationClient = new AuthenticationClient(sdk);
const dataManagementClient = new DataManagementClient(sdk);
Next, append the following code to the end of the services/aps.js
file:
// Data Management APIs
service.getHubs = async (accessToken) => {
const resp = await dataManagementClient.getHubs({ accessToken });
return resp.data;
};
service.getProjects = async (hubId, accessToken) => {
const resp = await dataManagementClient.getHubProjects(hubId, { accessToken });
return resp.data;
};
The method dataManagementClient.getHubProjects() only returns these projects that the current logged user is member of.
Create a APS.Hubs.cs
under the Models
subfolder with the following content:
using System.Collections.Generic;
using System.Threading.Tasks;
using Autodesk.DataManagement;
using Autodesk.DataManagement.Model;
public partial class APS
{
public async Task<IEnumerable<HubData>> GetHubs(Tokens tokens)
{
var dataManagementClient = new DataManagementClient();
var hubs = await dataManagementClient.GetHubsAsync(accessToken: tokens.InternalToken);
return hubs.Data;
}
public async Task<IEnumerable<ProjectData>> GetProjects(string hubId, Tokens tokens)
{
var dataManagementClient = new DataManagementClient();
var projects = await dataManagementClient.GetHubProjectsAsync(hubId, accessToken: tokens.InternalToken);
return projects.Data;
}
}
Create a APS.Hubs.cs
under the Models
subfolder with the following content:
using System.Collections.Generic;
using System.Threading.Tasks;
using Autodesk.DataManagement;
using Autodesk.DataManagement.Model;
public partial class APS
{
public async Task<IEnumerable<HubData>> GetHubs(Tokens tokens)
{
var dataManagementClient = new DataManagementClient();
var hubs = await dataManagementClient.GetHubsAsync(accessToken: tokens.InternalToken);
return hubs.Data;
}
public async Task<IEnumerable<ProjectData>> GetProjects(string hubId, Tokens tokens)
{
var dataManagementClient = new DataManagementClient();
var projects = await dataManagementClient.GetHubProjectsAsync(hubId, accessToken: tokens.InternalToken);
return projects.Data;
}
}
Server endpoints
Next, let's expose the new functionality to the client-side code through another set of endpoints. Data Management API returns plentiful data of the object. Our endpoints will extract partial data for client-side.
- Node.js & VSCode
- .NET & VSCode
- .NET & VS2022
Create a hubs.js
file under the routes
subfolder with the following content:
const express = require('express');
const { authRefreshMiddleware, getHubs, getProjects } = require('../services/aps.js');
let router = express.Router();
router.use('/api/hubs', authRefreshMiddleware);
router.get('/api/hubs', async function (req, res, next) {
try {
const hubs = await getHubs(req.internalOAuthToken.access_token);
//build the json response with some data of the hub
res.json(hubs.map(hub => ({type:hub.type, id: hub.id, name: hub.attributes.name,region:hub.attributes.region})));
} catch (err) {
next(err);
}
});
router.get('/api/hubs/:hub_id/projects', async function (req, res, next) {
try {
const projects = await getProjects(req.params.hub_id, req.internalOAuthToken.access_token);
//build the json response with some data of the project
res.json(projects.map(project => ({type:project.type, id: project.id, name: project.attributes.name, })));
} catch (err) {
next(err);
}
});
module.exports = router;
And mount the router to our server application by modifying server.js
:
const express = require('express');
const session = require('cookie-session');
const { PORT, SERVER_SESSION_SECRET } = require('./config.js');
let app = express();
app.use(express.static('wwwroot'));
app.use(session({ secret: SERVER_SESSION_SECRET, maxAge: 24 * 60 * 60 * 1000 }));
app.use(require('./routes/auth.js'));
app.use(require('./routes/hubs.js'));
app.listen(PORT, () => console.log(`Server listening on port ${PORT}...`));
Create a HubsController.cs
file under the Controllers
subfolder with the following content:
using System.Linq;
using System.Threading.Tasks;
using Autodesk.DataManagement.Model;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class HubsController : ControllerBase
{
private readonly APS _aps;
public HubsController(APS aps)
{
_aps = aps;
}
[HttpGet()]
public async Task<ActionResult> ListHubs()
{
var tokens = await AuthController.PrepareTokens(Request, Response, _aps);
if (tokens == null)
{
return Unauthorized();
}
return Ok(
from hub in await _aps.GetHubs(tokens)
select new { id = hub.Id, name = hub.Attributes.Name }
);
}
[HttpGet("{hub}/projects")]
public async Task<ActionResult> ListProjects(string hub)
{
var tokens = await AuthController.PrepareTokens(Request, Response, _aps);
if (tokens == null)
{
return Unauthorized();
}
return Ok(
from project in await _aps.GetProjects(hub, tokens)
select new { id = project.Id, name = project.Attributes.Name }
);
}
}
The controller handles several endpoints for browsing the content in other APS-based applications such as BIM 360 Docs and ACC. We will make use of these endpoints when building the UI part of the application.
Create a HubsController.cs
file under the Controllers
subfolder with the following content:
using System.Linq;
using System.Threading.Tasks;
using Autodesk.DataManagement.Model;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class HubsController : ControllerBase
{
private readonly APS _aps;
public HubsController(APS aps)
{
_aps = aps;
}
[HttpGet()]
public async Task<ActionResult> ListHubs()
{
var tokens = await AuthController.PrepareTokens(Request, Response, _aps);
if (tokens == null)
{
return Unauthorized();
}
return Ok(
from hub in await _aps.GetHubs(tokens)
select new { id = hub.Id, name = hub.Attributes.Name }
);
}
[HttpGet("{hub}/projects")]
public async Task<ActionResult> ListProjects(string hub)
{
var tokens = await AuthController.PrepareTokens(Request, Response, _aps);
if (tokens == null)
{
return Unauthorized();
}
return Ok(
from project in await _aps.GetProjects(hub, tokens)
select new { id = project.Id, name = project.Attributes.Name }
);
}
}
The controller handles several endpoints for browsing the content in other APS-based applications such as BIM 360 Docs and ACC. We will make use of these endpoints when building the UI part of the application.
Try it out
Start (or restart) the app from Visual Studio Code as usual, and navigate to http://localhost:8080/api/hubs in the browser. The server should respond with a JSON list of all the hubs you have access to.
Try to copy one hub Id, and use it in another address: http://localhost:8080/api/hubs/your-hub-id/projects. The server should respond with a JSON list of all projects available under the specified hub.
If you have skipped the login procedure in the previous step, or restarted your server application,
you may need to go to http://localhost:8080/api/auth/login
again to make sure that all the authentication data is available in cookies before testing
the /api/hubs
endpoint.
If you are using Google Chrome, consider installing JSON Formatter or a similar extension to automatically format JSON responses.