let me introduce you to my problem with updating existing files and kindly ask you for a fix suggestion :)
You will probably notice that I am using an older REST-like API called MFWSClient.
A newer version was published on GitHub: https://github.com/M-Files/Libraries.MFWSClient on [color=blue]28.3.2020[/color], but due to reasons and hope this version will not be deprecated, I stick with it.
I have two questions. You will notice.
As the M-Files Developer portal similarly states on: https://developer.m-files.com/APIs/REST-API/Updating-Objects/#updating-an-existing-file
if one desires to update an existing file, the following should be done:
1. Authenticate: (my code below)
client = new MFClient(pURL);
client.Authentication = client.Post<PrimitiveType<string>>("/server/authenticationtokens", new Authentication { Username = pUsername, Password = pPassword, VaultGuid = pVaultGUID }).Value;
client.Authentication = client.Get<Vault>("/session/vault").Authentication;
Thanks to [color=green]SessionInfo[/color] I am able to check the user related information:
SessionInfo sessionInfo = client.Get<SessionInfo>("/session");
/*
Console.WriteLine("THE VALUES LISTED BELOW");
// Console output
sessionInfo.AccountName = ADMIN
sessionInfo.ACLMode = AutomaticPermissionsWithComponents
sessionInfo.AuthenticationType = SpecificMFilesUser
sessionInfo.CanForceUndoCheckout = True
sessionInfo.CanManageCommonUISettings = True
sessionInfo.CanManageCommonViews = True
sessionInfo.CanManageTraditionalFolders = True
sessionInfo.CanMaterializeViews = True
sessionInfo.CanSeeAllObjects = True
sessionInfo.CanSeeDeletedObjects = True
sessionInfo.InternalUser = True
sessionInfo.LicenseAllowsModifications = True
sessionInfo.UserID = 9
*/
It seems like I should be on the correct account as well as have the permissions to perform the desired activity. :)
2. Check out an existing object: (my code below)
ObjectVersion objectVersion = client.Put<ObjectVersion>(string.Format("/objects/{0}/{1}/{2}/checkedout", pType, pObjectID, pVersion),
new PrimitiveType<MFCheckOutStatus>() { Value = MFCheckOutStatus.CheckOutToMe });
Thanks to [color=green]ObjectVersion[/color] I am able to check the object related information:
ObjectVersion objectVersion = client.Get<ObjectVersion>(string.Format("/objects/{0}/{1}/{2}", pType, pObjectID, pVersion));
/*
Console.WriteLine("THE VALUES LISTED BELOW");
// Console output
objectVersion.CheckedOutToUserName = Administrator
objectVersion.CheckedOutTo = 9
objectVersion.ObjectCheckedOut = True
objectVersion.ObjectCheckedOutToThisUser = True
*/
Looking at the console, it seems like the object was checked out to me. :)
[color=red]But looking at M-Files Explorer it is apparently not - Please see the image:[/color] https://imgur.com/MUlhhIg
Question #1. What did I do wrong here?
3. Prepare and update / upload a file: (my code below)
ObjectFile[] files = client.Get<ObjectFile[]>(string.Format("/objects/{0}/{1}/{2}/files", pType, pObjectID, pVersion));
if (files.Length == 0) return;
/*
DownloadFileAsStream(); <- I was able to extract the code for this from the new MFWSClient API. The older one did not provide this functionality.
ConvertFileToReadableFormat();
SaveFileOnHardDrive();
OpenAndEditFile();
*/
ObjectVersion objectVersion = client.Put<ObjectVersion>(string.Format("/objects/{0}/{1}/{2}/files/{3}/content", pType, pObjectID, pVersion, files[0].ID),
new System.Net.Http.StreamContent(new FileInfo(Path.GetFullPath(pFilePath)).OpenRead()));
I am aware the last REST-like call might not be entirely correct,
but I did my best to search for the right examples on the M-Files Documentation sources,
but I have to say that some of them are missing or not matching the API publised on GitHub.
I apologize if I missed anything and will be grateful for a hint on this one.
Question #2. What is the correct way?
(I see a lot of forums that mention: "application/octet-stream" with posting random binary formatfiles across the interwebs)
(I also noticed the client.Put<T>(); method originally does not account for this)
4. Check back in (not important in this context)
Thank you a lot M-Files staff & fellow developers, perhaps this post is useful to other newcomers as well.
Edit:
This is the method performing the GET / PUT requests:
public T Get<T>(string pPath) {
return (T)PerformRequest("GET", pPath, null, typeof(T));
}
public T Put<T>(string pPath, object pContent) {
return (T)PerformRequest("PUT", pPath, pContent, typeof(T));
}
private object PerformRequest(string pMethod, string pPath, object pContent, Type pReturnType) {
if (pPath[0] == '/')
pPath = pPath.Substring(1);
string uri = EndPoint + pPath;
if (pMethod == "PUT" || pMethod == "DELETE") {
if (uri.Contains("?")) uri += "&";
else uri += "?";
uri += "_method=" + pMethod;
}
WebRequest request = WebRequest.Create(uri);
request.Method = (pMethod.ToUpper() == "GET") ? "GET" : "POST";
if (!string.IsNullOrEmpty(Authentication)) request.Headers["X-Authentication"] = Authentication;
if (pContent != null) {
if (pContent is Stream) {
Stream requestStream = request.GetRequestStream();
Stream sourceStream = (Stream)pContent;
sourceStream.CopyTo(requestStream);
requestStream.Flush();
requestStream.Close();
} else {
Stream requestStream = request.GetRequestStream();
DataContractJsonSerializer requestSerializer = new DataContractJsonSerializer(pContent.GetType());
requestSerializer.WriteObject(requestStream, pContent);
requestStream.Flush();
requestStream.Close();
}
}
WebResponse response;
try {
response = request.GetResponse();
} catch (WebException pException) {
HandleError(pException);
throw;
}
if (pReturnType == null) return null;
if (pReturnType == typeof(string)) return new StreamReader(response.GetResponseStream()).ReadToEnd();
if (pReturnType == typeof(Stream)) return response.GetResponseStream();
if (response.GetResponseStream() == null) return null;
return new DataContractJsonSerializer(pReturnType).ReadObject(responseStream);
}
