This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

REST API - Updating an existing file

Good evening everyone,

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);
}
Parents Reply Children
No Data