Getting Error while uploading file by multipart "Failed to create the attachment. File part might be missing in the request."

deb20
Kilo Contributor

I am trying to upload file using multipart from C# console application but I am always getting the same error "Failed to create the attachment. File part might be missing in the request.".

 This is my code to upload the attachment.


tableSysId = "49b4d240db86d3002a889ae8db9619f8";

filePath = @"C:\Users\xxxxxdddd\Pictures\xx.png";

using (var client = new HttpClient())

{

string[] array = filePath.Split('\\');

string filename = array[array.Length - 1].ToString();

client.BaseAddress = new Uri("https://xxxxxx.service-now.com/");

client.DefaultRequestHeaders.Add("Authorization", "basic c2xhY2tfYm90OlNsYWNrYm90QDEyMw==");

client.DefaultRequestHeaders.Add("Accept", "*/*");

MultipartFormDataContent content = new MultipartFormDataContent();

//content.Headers.ContentType.MediaType = "multipart/form-data";

ByteArrayContent fileStream = new ByteArrayContent(File.ReadAllBytes(filePath));

fileStream.Headers.ContentType = new MediaTypeHeaderValue("image/png");

fileStream.Headers.Add("Content-Disposition", "attachment; filename=fileName.png");

content.Add(new StringContent("incident"), "table_name");

content.Add(new StringContent(tableSysId), "table_sys_id");

content.Add(fileStream, "file","file.png");

 

HttpResponseMessage response = await client.PostAsync("api/now/attachment/upload", content);

string returnString = await response.Content.ReadAsStringAsync();

return returnString;

Thanks in Advance.

1 ACCEPTED SOLUTION

gcubed_
Tera Contributor

I was fast approaching a deadline last time I was trying to use this which is why I dropped back to using ECCQueue.

I had some time last night to look at this:

First, I got it working via SoapUI which gave me a working request payload.  I then wired up a simple console application with a httpclient logger to dump the request and response payload.

So this gets the same fail to create error.

using (var client = new HttpClient(loggingHandler))
	{
		var array = filePath.Split('\\');
		var filename = array[array.Length - 1].ToString();
		client.BaseAddress = new Uri("https://servicenow.service-now.com");
		client.DefaultRequestHeaders.Add("Authorization", " Basic x=");
		client.DefaultRequestHeaders.Add("Accept", "*/*");
		var content = new MultipartFormDataContent(boundry);

		var fileStream = new ByteArrayContent(File.ReadAllBytes(filePath));
		fileStream.Headers.Remove("Content-Type");
		fileStream.Headers.Add("Content-Type", "application/octet-stream");
		fileStream.Headers.Add("Content-Transfer-Encoding","binary");
		fileStream.Headers.Add("Content-Disposition", $"form-data;name=uploadFile; filename={filename}");
		content.Add(new StringContent(tableName), "table_name");
		content.Add(new StringContent(tableSysId), "table_sys_id");
		content.Add(fileStream, "uploadFile");

		var response = await client.PostAsync("api/now/attachment/upload", content);

		return await response.Content.ReadAsStringAsync();
	}

 

The only difference between the C# request payload and the SoapUI  payload was double qoutes around the keys in the headers.

This one works.

 

using (var client = new HttpClient(loggingHandler))
	{
		var array = filePath.Split('\\');
		var filename = array[array.Length - 1].ToString();
		client.BaseAddress = new Uri("https://servicenow.service-now.com");
		client.DefaultRequestHeaders.Add("Authorization", " Basic x=");
		client.DefaultRequestHeaders.Add("Accept", "*/*");
		var content = new MultipartFormDataContent(boundry);

		var fileStream = new ByteArrayContent(File.ReadAllBytes(filePath));
		fileStream.Headers.Remove("Content-Type");
		fileStream.Headers.Add("Content-Type", "application/octet-stream");
		fileStream.Headers.Add("Content-Transfer-Encoding","binary");
		fileStream.Headers.Add("Content-Disposition", $"form-data;name=\"uploadFile\"; filename=\"{filename}\"");
		content.Add(new StringContent(tableName), "\"table_name\"");
		content.Add(new StringContent(tableSysId), "\"table_sys_id\"");
		content.Add(fileStream, "uploadFile");

		var response = await client.PostAsync("api/now/attachment/upload", content);

		return await response.Content.ReadAsStringAsync();
	}

 

V/r,

Gene

 

View solution in original post

3 REPLIES 3

gcubed_
Tera Contributor

I wasn't able to get this to work a while back.  I dropped back to using EccQueue.

 

If you figure it out, please post the solution.

 

V/r,

Gene

 

        [WebMethod]
        public Boolean UploadAttachementPayload(ServiceNowAuthenication serviceNowAuthenication, String tableName, String fileName,
            String contenType, String sysId, String payLoad)
        {
            try
            {
                var eccQueue = SysEccQueueFactory(serviceNowAuthenication);
                NLogger.Info(eccQueue.Url);
                var insert = new ecc.insert
                {
                    agent = "MidServerWebService",
                    topic = "AttachmentCreator",
                    name = $"{fileName.Trim()}:{contenType.Trim()}",
                    source = $"{tableName.Trim()}:{sysId.Trim()}",
                    payload = payLoad
                };
                eccQueue.insert(insert);
                return true;
            }
            catch (Exception ex)
            {
                NLogger.Error(ex.Message);
            }
            return false;
        }

        [WebMethod]
        public ScriptedResponse AttachementToScriptedResponse(ServiceNowAuthenication serviceNowAuthenication, String tableSysId, String tableName, String fileName)
        {
            try
            {
                var serviceNowAttachmentService = SysAttachmentService(serviceNowAuthenication);
                var execute = new scripted.execute
                {
                    operation = "getAttachmentContents",
                    table_name = tableName,
                    table_sys_id = tableSysId,
                    file_name = fileName
                };
                var responsePayload =  serviceNowAttachmentService.execute(execute);
                var scriptedResponse = new ScriptedResponse
                {
                    Code = responsePayload.code,
                    Payload = responsePayload.payload
                };

                return scriptedResponse;
            }
            catch (Exception ex)
            {
                NLogger.Error(ex.Message);
            }
            return new ScriptedResponse();
        }

gcubed_
Tera Contributor

I was fast approaching a deadline last time I was trying to use this which is why I dropped back to using ECCQueue.

I had some time last night to look at this:

First, I got it working via SoapUI which gave me a working request payload.  I then wired up a simple console application with a httpclient logger to dump the request and response payload.

So this gets the same fail to create error.

using (var client = new HttpClient(loggingHandler))
	{
		var array = filePath.Split('\\');
		var filename = array[array.Length - 1].ToString();
		client.BaseAddress = new Uri("https://servicenow.service-now.com");
		client.DefaultRequestHeaders.Add("Authorization", " Basic x=");
		client.DefaultRequestHeaders.Add("Accept", "*/*");
		var content = new MultipartFormDataContent(boundry);

		var fileStream = new ByteArrayContent(File.ReadAllBytes(filePath));
		fileStream.Headers.Remove("Content-Type");
		fileStream.Headers.Add("Content-Type", "application/octet-stream");
		fileStream.Headers.Add("Content-Transfer-Encoding","binary");
		fileStream.Headers.Add("Content-Disposition", $"form-data;name=uploadFile; filename={filename}");
		content.Add(new StringContent(tableName), "table_name");
		content.Add(new StringContent(tableSysId), "table_sys_id");
		content.Add(fileStream, "uploadFile");

		var response = await client.PostAsync("api/now/attachment/upload", content);

		return await response.Content.ReadAsStringAsync();
	}

 

The only difference between the C# request payload and the SoapUI  payload was double qoutes around the keys in the headers.

This one works.

 

using (var client = new HttpClient(loggingHandler))
	{
		var array = filePath.Split('\\');
		var filename = array[array.Length - 1].ToString();
		client.BaseAddress = new Uri("https://servicenow.service-now.com");
		client.DefaultRequestHeaders.Add("Authorization", " Basic x=");
		client.DefaultRequestHeaders.Add("Accept", "*/*");
		var content = new MultipartFormDataContent(boundry);

		var fileStream = new ByteArrayContent(File.ReadAllBytes(filePath));
		fileStream.Headers.Remove("Content-Type");
		fileStream.Headers.Add("Content-Type", "application/octet-stream");
		fileStream.Headers.Add("Content-Transfer-Encoding","binary");
		fileStream.Headers.Add("Content-Disposition", $"form-data;name=\"uploadFile\"; filename=\"{filename}\"");
		content.Add(new StringContent(tableName), "\"table_name\"");
		content.Add(new StringContent(tableSysId), "\"table_sys_id\"");
		content.Add(fileStream, "uploadFile");

		var response = await client.PostAsync("api/now/attachment/upload", content);

		return await response.Content.ReadAsStringAsync();
	}

 

V/r,

Gene

 

deb20
Kilo Contributor

Hi Gene,

Thanks a lot for the sleuthing and helping to resolve this. This really did work for me too.

 

Regards

Deb