
Announcements
Hi everyone,
I am struggling big time trying to understand how document locations / sharepoint sites work in the context of a model driven app.
All I want to do is to associate a record, say a Project to an existing Sharepoint document library I have created called Files
Ultimately, I want to make a Flow so as a folder structure is automatically created like so, and a folder location is associated as the document location to a record;
Sharepoint-site/Files/<staff-member-name/<project-name>/<<content-here>>
But I can't even figure out how to do that by manually creating a document location?
I have a sharepoint site created in the Sharepoint Sites table but when I try to create a document location, I can't put in a sub folder structure under Relative URL because the / character is not accepted - I feel like I'm either losing my mind and/or doing something super dumb.
Any guidance super appreciated.
Cheers
Well, to start, Document Locations are only one part of the story: The map that takes you from your Dataverse record to a SharePoint folder goes through one (or more) Document Location records, then eventually to a SharePoint Site record, and the composite of all those is the url path to your SharePoint folder.
But even that is misleadingly simple, because this whole structure was never built to enable you to manually overwrite. It was all designed for the system to automatically build these records for you - for Dataverse to create the folder (and any parent folders) automatically when you create the Dataverse record. And this is exactly what it does once you actually turn on and configure document management for a record.
That's not to say you can't trick it - you can absolutely write code (or even PowerAutomate flows) that track down that chain of records and overwrite their values to point at some other pre-existing location in SharePoint, or even to create new records to accomplish the same right alongside the auto-generated ones.
If you look at the code in my recent blog post here you'll see a section where I work up that chain of records, and it should be helpful to you if you want to do something similar.
const buildurl = (location: LocationOption, id: string, type: string, url: string) => {
if(type.toLocaleLowerCase() === "sharepointdocumentlocation"){
props.context.webAPI.retrieveRecord(type, id, "").then(
(success) => {
if(success._parentsiteorlocation_value !== success.sitecollectionid){
buildurl(location, success._parentsiteorlocation_value, "sharepointdocumentlocation", success.relativeurl + "/" + url);
}
else{
buildurl(location, success._parentsiteorlocation_value, "sharepointsite", success.relativeurl + "/" + url);
}
},
(error) => {
console.log(error);
}
)
} else { //sharepointsite
props.context.webAPI.retrieveRecord(type, id, "").then(
(success) => {
if(typeof(map) === "undefined"){
map =[{ key: location.id, url: success.absoluteurl + "/" + url }];
}else{
if(!map.includes({ key: location.id, url: success.absoluteurl + "/" + url }))
map.push({ key: location.id, url: success.absoluteurl + "/" + url });
}
let opts = options;
if(!opts.includes(props.dropdownOptions.find(x => x.id === location.id)!.dropdownOption))
opts.push(props.dropdownOptions.find(x => x.id === location.id)!.dropdownOption);
setOptions(opts);
setSelectedItem(options[0]);
setSelectedUrl(map?.find(x => x.key === options[0].key)?.url);
},
(error) => {
console.log(error);
}
)
}
};
Essentially, I keep looping, grabbing the parent site or location id and comparing it to the sitecollectionid until they match. As long as they don't match, I know I have another parent location, and I keep building that URL from the back to the front. As soon as they match, I know I have no more parent locations, and I only have a parent Site, so I grab the parent site instead, stick that root url on the front of the string I've been building, and presto! I have my URL.
In your case, you're trying to do the same thing, just in the other order. You'll need to take the URL of your SharePoint folder, and split it: take the root URL and make a Site with that, then build a chain of child locations, always pointing one step up the ladder and always referencing their parentsiteid until you get to the end of the URL, then relate that last Location record to your Dataverse record and it should present the SharePoint folder you're trying to manually force.
*full disclosure, I've never actually tried to build this chain of records, only to read it. So it is possible the OOB operations are doing more in the background and even if you do this it won't solve your problems. But, here's hoping! 🤞