Greetings folks,
I'm a bit of a Vault newbie in general and have been getting into the SDK for building a Vault extension the last few weeks. I'm a pretty experienced coder but am struggling to get a few things done that I would have expected to be fairly simple and standard user flows.
Too long don't want to read:
I'm looking for a simple way to update Properties on Files and Folders that I am creating through my Vault Explorer Extension. Preferably before creation to avoid incrementing version numbers unnecessarily. I'd like to use C# as I've written my extension in that so far.
Some context:
At present we create Projects in Vault for the normal Vault like capacities.
We also track information in various other places relevant to these projects.
To prevent double handling we would like to build a Vault Explorer Extension to achieve the following:
Add an action menu to the Nav Selection Set for right clicks on folders.
On activation display a form for data input relevant to the project.
On form submission, generate a new Vault Project Folder (and call some APIs etc not relevant to the questions here).
Populate some Custom Properties on the Folder.
Optionally copy some files in from our templates folder (and update some properties on them as well).
I have currently gotten through all of the UI setup. On form submission I am generating a new Folder using the Data Standards numbering scheme. I am also successfully copying the template files into the Folder.
Now for the problems I am facing. For the template copying I am not sure I am doing it in the most efficient or "best practice" way. I am a bit surprised there isn't a method on the DocumentServices to the effect of "MakeDuplicateFile("path/to/file", "output/folder") like there is for the MoveFile. Here's what I ended up with:
private FileIteration CopyTemplate(string inputFile, long outputFolderId, string outputFileName)
{
WebServices.File[] files = _connection.WebServiceManager.DocumentService.FindLatestFilesByPaths(new[] { inputFile });
long fileMasterId = files[0].MasterId;
ByteArray[] ticket = _connection.WebServiceManager.DocumentService.GetDownloadTicketsByMasterIds(new[] { fileMasterId });
FileAssocParam[] fileAssocParams = new FileAssocParam[0];
BOM bom = new BOM();
System.IO.Stream fileStream = new MemoryStream(ticket[0].Bytes);
IDictionary<long, Currency.Entities.Folder> projectFolder = _connection.FolderManager.GetFoldersByIds(new[] { outputFolderId });
FileIteration newVersion = _connection.FileManager.AddFile(projectFolder[outputFolderId], outputFileName, "", DateTime.Now, fileAssocParams, bom, FileClassification.None, false, fileStream);
return newVersion;
}
Now for the crux of why I am here petitioning for your assistance in these dark times. I have just spent the better part of a business day looking to do the properties section of my use case, and am not having much luck.
I almost made it for the File properties using:
private void UpdateFileProperties(FileIteration file, Dictionary<string, string> formData)
{
// Update the properties of the file
WebServices.File existingFile = _documentService.GetFileById(file.EntityIterationId);
PropDef[] atts = _propertyService.GetPropertyDefinitionsByEntityClassId("FILE");
PropInstParam[] properties = new PropInstParam[0];
foreach (PropDef att in atts)
{
if (formData.ContainsKey(att.DispName))
{
PropInstParam property = new PropInstParam();
properties.Append(property);
}
}
PropInstParamArray propsArray = new PropInstParamArray();
propsArray.Items = properties;
PropInstParamArray[] propInstParamArrays = new PropInstParamArray[] { propsArray };
long[] fileIds = new long[] { existingFile.MasterId };
_documentService.UpdateFileProperties(fileIds, propInstParamArrays);
}
but got agonisingly close to the finish line before hitting the "File isn't checked out" error for the last call. I can go the effort of adding the checkout logic, although it seems to add complexity since the method call involves local paths and machines and I'd rather not have a local version of the file. It also means that each template copied in would be immediately set to iteration 2. I found the AddFileWithBehaviors method but that requires an input file to copy the properties from (and I'm not sure it wouldn't cause issues with random other behaviors but I could look into that). I could update the properties on the template before I duplicated it each time and then at least that file would be the one incrementing versions which isn't super relevant since it's just a template... but it again feels over engineered for something which feels like it should be common place.
As for the Folder properties I haven't even gotten that far. The UpdateFileProperties throws a file not found error when given a folder id (not surprisingly), and there are no other methods I can find that seem to be set for this.
I have investigated the DocumentService, DocumentServiceExtensions, PropertyService, and various others. I've also tried searching here and found a few references to VDS but I'd rather maintain the logic in the one application using the one language (I'm new to C# and would rather not have to delve into PowerShell at the same time unless I need to).
Any help much appreciated. I hope the war and peace version of my plight wasn't too gruelling to read.
Solved! Go to Solution.
Greetings folks,
I'm a bit of a Vault newbie in general and have been getting into the SDK for building a Vault extension the last few weeks. I'm a pretty experienced coder but am struggling to get a few things done that I would have expected to be fairly simple and standard user flows.
Too long don't want to read:
I'm looking for a simple way to update Properties on Files and Folders that I am creating through my Vault Explorer Extension. Preferably before creation to avoid incrementing version numbers unnecessarily. I'd like to use C# as I've written my extension in that so far.
Some context:
At present we create Projects in Vault for the normal Vault like capacities.
We also track information in various other places relevant to these projects.
To prevent double handling we would like to build a Vault Explorer Extension to achieve the following:
Add an action menu to the Nav Selection Set for right clicks on folders.
On activation display a form for data input relevant to the project.
On form submission, generate a new Vault Project Folder (and call some APIs etc not relevant to the questions here).
Populate some Custom Properties on the Folder.
Optionally copy some files in from our templates folder (and update some properties on them as well).
I have currently gotten through all of the UI setup. On form submission I am generating a new Folder using the Data Standards numbering scheme. I am also successfully copying the template files into the Folder.
Now for the problems I am facing. For the template copying I am not sure I am doing it in the most efficient or "best practice" way. I am a bit surprised there isn't a method on the DocumentServices to the effect of "MakeDuplicateFile("path/to/file", "output/folder") like there is for the MoveFile. Here's what I ended up with:
private FileIteration CopyTemplate(string inputFile, long outputFolderId, string outputFileName)
{
WebServices.File[] files = _connection.WebServiceManager.DocumentService.FindLatestFilesByPaths(new[] { inputFile });
long fileMasterId = files[0].MasterId;
ByteArray[] ticket = _connection.WebServiceManager.DocumentService.GetDownloadTicketsByMasterIds(new[] { fileMasterId });
FileAssocParam[] fileAssocParams = new FileAssocParam[0];
BOM bom = new BOM();
System.IO.Stream fileStream = new MemoryStream(ticket[0].Bytes);
IDictionary<long, Currency.Entities.Folder> projectFolder = _connection.FolderManager.GetFoldersByIds(new[] { outputFolderId });
FileIteration newVersion = _connection.FileManager.AddFile(projectFolder[outputFolderId], outputFileName, "", DateTime.Now, fileAssocParams, bom, FileClassification.None, false, fileStream);
return newVersion;
}
Now for the crux of why I am here petitioning for your assistance in these dark times. I have just spent the better part of a business day looking to do the properties section of my use case, and am not having much luck.
I almost made it for the File properties using:
private void UpdateFileProperties(FileIteration file, Dictionary<string, string> formData)
{
// Update the properties of the file
WebServices.File existingFile = _documentService.GetFileById(file.EntityIterationId);
PropDef[] atts = _propertyService.GetPropertyDefinitionsByEntityClassId("FILE");
PropInstParam[] properties = new PropInstParam[0];
foreach (PropDef att in atts)
{
if (formData.ContainsKey(att.DispName))
{
PropInstParam property = new PropInstParam();
properties.Append(property);
}
}
PropInstParamArray propsArray = new PropInstParamArray();
propsArray.Items = properties;
PropInstParamArray[] propInstParamArrays = new PropInstParamArray[] { propsArray };
long[] fileIds = new long[] { existingFile.MasterId };
_documentService.UpdateFileProperties(fileIds, propInstParamArrays);
}
but got agonisingly close to the finish line before hitting the "File isn't checked out" error for the last call. I can go the effort of adding the checkout logic, although it seems to add complexity since the method call involves local paths and machines and I'd rather not have a local version of the file. It also means that each template copied in would be immediately set to iteration 2. I found the AddFileWithBehaviors method but that requires an input file to copy the properties from (and I'm not sure it wouldn't cause issues with random other behaviors but I could look into that). I could update the properties on the template before I duplicated it each time and then at least that file would be the one incrementing versions which isn't super relevant since it's just a template... but it again feels over engineered for something which feels like it should be common place.
As for the Folder properties I haven't even gotten that far. The UpdateFileProperties throws a file not found error when given a folder id (not surprisingly), and there are no other methods I can find that seem to be set for this.
I have investigated the DocumentService, DocumentServiceExtensions, PropertyService, and various others. I've also tried searching here and found a few references to VDS but I'd rather maintain the logic in the one application using the one language (I'm new to C# and would rather not have to delve into PowerShell at the same time unless I need to).
Any help much appreciated. I hope the war and peace version of my plight wasn't too gruelling to read.
Solved! Go to Solution.
Solved by Nick_Hall. Go to Solution.
Hi
Two things immediately come to mind
Hope that helps
Nick
Hi
Two things immediately come to mind
Hope that helps
Nick
Thank you @Nick_Hall that is a great help to start. I'm not super familiar with the business side of Vault either so I wasn't sure how relevant an extra version number is but if increasing it to update the properties is the expected behaviour the I'll definitely just add in the checkout code for the update.
Do you have advice for me on the Folder section? Are Folders considered Files when it comes to the UpdateFileProperties method? If not is there another method that I'm missing in the SDK?
It's also maybe worth noting for you and others that the properties aren't reliant on a two way binding with the file itself, they are purely metadata to be stored for external reference.
Thank you for the help so far. I hope your day is going well.
Regards,
Keone Martin
Thank you @Nick_Hall that is a great help to start. I'm not super familiar with the business side of Vault either so I wasn't sure how relevant an extra version number is but if increasing it to update the properties is the expected behaviour the I'll definitely just add in the checkout code for the update.
Do you have advice for me on the Folder section? Are Folders considered Files when it comes to the UpdateFileProperties method? If not is there another method that I'm missing in the SDK?
It's also maybe worth noting for you and others that the properties aren't reliant on a two way binding with the file itself, they are purely metadata to be stored for external reference.
Thank you for the help so far. I hope your day is going well.
Regards,
Keone Martin
On the subject of versions, in my opinion a few extra versions don't matter, because it's the Revision that really matters. Others may disagree (but)
This is especially true if the underlying file doesn't change (as in the use case you describe), because it only costs you a few database entries - Vault does not make a copy of the file if it is the same as the previous version
Hopefully that will get you through the next stage with your project
Nick
On the subject of versions, in my opinion a few extra versions don't matter, because it's the Revision that really matters. Others may disagree (but)
This is especially true if the underlying file doesn't change (as in the use case you describe), because it only costs you a few database entries - Vault does not make a copy of the file if it is the same as the previous version
Hopefully that will get you through the next stage with your project
Nick
Thanks Nick,
A touch embarrassed that I missed the Folder update method on the Extensions class.
I very much appreciate your assistance and have successfully implemented the things I was looking to do.
For anyone who may find my solutions helpful in the future:
Files:
private void UpdateFileProperties(FileIteration file, Dictionary<string, string> formData)
{
// Update the properties of the file
WebServices.File checkedOutFile = CheckoutFile(file.EntityIterationId);
PropDef[] atts = _propertyService.GetPropertyDefinitionsByEntityClassId("FILE");
List<PropInstParam> properties = new List<PropInstParam>();
foreach (PropDef att in atts)
{
if (formData.ContainsKey(att.DispName))
{
PropInstParam property = new PropInstParam();
property.PropDefId = att.Id;
property.Val = formData[att.DispName];
properties.Add(property);
}
}
PropInstParamArray propsArray = new PropInstParamArray();
propsArray.Items = properties.ToArray();
PropInstParamArray[] propInstParamArrays = new PropInstParamArray[] { propsArray };
long[] fileIds = new long[] { checkedOutFile.MasterId };
_documentService.UpdateFileProperties(fileIds, propInstParamArrays);
}
private WebServices.File CheckoutFile (long fileId)
{
CheckoutFileOptions options = new CheckoutFileOptions();
string machine = Environment.MachineName;
string tempFolder = Path.GetTempPath();
string comment = "";
ByteArray downloadTicket = new ByteArray();
WebServices.File file = _documentService.CheckoutFile(fileId, options, machine, tempFolder, comment, out downloadTicket);
return file;
}
Please note that this code doesn't check the file back in, as that was the desired state.
Folders:
private void UpdateFolderProperties(long folderId, Dictionary<string, string> formData)
{
// Update the properties of the file
PropDef[] atts = _propertyService.GetPropertyDefinitionsByEntityClassId("FLDR");
List<PropInstParam> properties = new List<PropInstParam>();
foreach (PropDef att in atts)
{
if (formData.ContainsKey(att.DispName))
{
PropInstParam property = new PropInstParam();
property.PropDefId = att.Id;
property.Val = formData[att.DispName];
properties.Add(property);
}
}
PropInstParamArray propsArray = new PropInstParamArray();
propsArray.Items = properties.ToArray();
PropInstParamArray[] propInstParamArrays = new PropInstParamArray[] { propsArray };
long[] folderIds = new long[] { folderId };
_documentServiceExtensions.UpdateFolderProperties(folderIds, propInstParamArrays );
}
Thanks Nick,
A touch embarrassed that I missed the Folder update method on the Extensions class.
I very much appreciate your assistance and have successfully implemented the things I was looking to do.
For anyone who may find my solutions helpful in the future:
Files:
private void UpdateFileProperties(FileIteration file, Dictionary<string, string> formData)
{
// Update the properties of the file
WebServices.File checkedOutFile = CheckoutFile(file.EntityIterationId);
PropDef[] atts = _propertyService.GetPropertyDefinitionsByEntityClassId("FILE");
List<PropInstParam> properties = new List<PropInstParam>();
foreach (PropDef att in atts)
{
if (formData.ContainsKey(att.DispName))
{
PropInstParam property = new PropInstParam();
property.PropDefId = att.Id;
property.Val = formData[att.DispName];
properties.Add(property);
}
}
PropInstParamArray propsArray = new PropInstParamArray();
propsArray.Items = properties.ToArray();
PropInstParamArray[] propInstParamArrays = new PropInstParamArray[] { propsArray };
long[] fileIds = new long[] { checkedOutFile.MasterId };
_documentService.UpdateFileProperties(fileIds, propInstParamArrays);
}
private WebServices.File CheckoutFile (long fileId)
{
CheckoutFileOptions options = new CheckoutFileOptions();
string machine = Environment.MachineName;
string tempFolder = Path.GetTempPath();
string comment = "";
ByteArray downloadTicket = new ByteArray();
WebServices.File file = _documentService.CheckoutFile(fileId, options, machine, tempFolder, comment, out downloadTicket);
return file;
}
Please note that this code doesn't check the file back in, as that was the desired state.
Folders:
private void UpdateFolderProperties(long folderId, Dictionary<string, string> formData)
{
// Update the properties of the file
PropDef[] atts = _propertyService.GetPropertyDefinitionsByEntityClassId("FLDR");
List<PropInstParam> properties = new List<PropInstParam>();
foreach (PropDef att in atts)
{
if (formData.ContainsKey(att.DispName))
{
PropInstParam property = new PropInstParam();
property.PropDefId = att.Id;
property.Val = formData[att.DispName];
properties.Add(property);
}
}
PropInstParamArray propsArray = new PropInstParamArray();
propsArray.Items = properties.ToArray();
PropInstParamArray[] propInstParamArrays = new PropInstParamArray[] { propsArray };
long[] folderIds = new long[] { folderId };
_documentServiceExtensions.UpdateFolderProperties(folderIds, propInstParamArrays );
}
Can't find what you're looking for? Ask the community or share your knowledge.