0

I am trying to send a pdf file from javascript to a rest wcf service.

The service expects an array of byte with the following signature The trick is in the byte array parameter, all the others are working fine

[OperationContract]
[WebInvoke(UriTemplate = "rest/{sessionToken}/ImportNewTemplate?commit={commit}&createApplication={createApplication}&templateName={templateName}&option={option}")]
[CloudMethod(Group = "02. Templates", Description = "Import a new template in the platform.", HelpFile = "ListPaperTemplate.aspx")]
[CloudParameter(Name = "sessionToken", Description = "session token", HelpFile = "ServiceAPIDoc.aspx?q=sessionToken")]
[CloudParameter(Name = "createApplication", Description = "Create a standalone application linked to this template.")]
[CloudParameter(Name = "commit", Description = "Commit the upload ? if true, the template will be imported, else the return just allow you to preview template description.")]
[CloudParameter(Name = "templateName", Description = "Name of the new template. Only valid for single pdf upload. If the files are zipped, the file name in the zip will be used instead")]
[CloudParameter(Name = "templateFile", Description = "Can be a PDF file, or a zip file containing a flat pdf + xml definition", HelpFile = "ServiceAPIDoc.aspx?q=templateFile")]
CloudObjects.TemplateImportation ImportNewTemplate(string sessionToken, bool commit, bool createApplication, byte[] templateFile, string templateName, string option);

this is what I use from the javascript end to send the pdf file

const file = e.target.files[0];

// Encode the file using the FileReader API
const reader = new FileReader();
var fileByteArray = [];

reader.onloadend = async (e) => {               
    const arrayBuffer = e.target.result,
          array = new Uint8Array(arrayBuffer);
    for (const a of array) {
        console.log(a);
        fileByteArray.push(a);
    }
    
    let ret = await dispatch('createTemplate', {name: this.newForm.name, pdf:fileByteArray, save:false});
    await this.$store.dispatch('hideLoadingScreen')
    // Logs data:<type>;base64,wL2dvYWwgbW9yZ...
};
reader.onerror = async () => {
    await this.$store.dispatch('hideLoadingScreen')
}
reader.onabort = async () => {
    await this.$store.dispatch('hideLoadingScreen')
}
            
await this.$store.dispatch('showLoadingScreen');

reader.readAsArrayBuffer(file);    

And here is the code to send it to the rest service

let url = `${getters.getServiceUrl}ImportNewTemplate?templateName=${name}&commit=${save || true}`

const xhr = new XMLHttpRequest;
xhr.open("POST", url, false);
xhr.setRequestHeader('Content-Type', 'application/json');
let response = await   xhr.send(pdf);

However every time I get an error from the service when it tries to deserialise the byte array.

The exception message is 'There was an error deserializing the object of type System.Byte[]. End element 'root' from namespace '' expected.

I have tried a lot of alternatives but nothing works.

Any suggestions are welcome !

Thanks

Alexander
  • 4,420
  • 7
  • 27
  • 42
user2097439
  • 201
  • 2
  • 16
  • The WCF service expects XML data with request. You need to examine WSDL of the service to understand how to create correct request. – Alexander Aug 27 '22 at 17:05
  • It does work with xml but there is a binding for rest/json as well – user2097439 Aug 27 '22 at 20:56
  • Based on the error message, check out [this solution](https://stackoverflow.com/questions/15842136/error-deserializing-the-object-of-type-end-element-from-namespace). – Jiayao Aug 29 '22 at 07:04

1 Answers1

0

For those interested, the trick was to add JSON.stringify to the returned array.

So: xhr.send(JSON.stringify(pdf))

would do the trick

user2097439
  • 201
  • 2
  • 16