The CreatorCon Call for Content is officially open! Get started here.

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