Search code examples
python-3.xrestencodingdynamics-crmmicrosoft-dynamics

Add attachment to lead in MS Dynamics using Rest API


Does anyone know how to upload an attachment to existing lead entity in MS Dynamics using Rest API? I tried to follow this post using python code, but got an error saying

<Response [400]> b'{"error":{"code":"0x0","message":"An error occurred while validating input parameters: System.ArgumentException: Stream was not readable.\r\n at System.IO.StreamReader..ctor(Stream stream, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean leaveOpen)\r\n at System.IO.StreamReader..ctor(Stream stream, Encoding encoding)\r\n at Microsoft.OData.JsonLight.ODataJsonLightInputContext.CreateTextReader(Stream messageStream, Encoding encoding)\r\n at Microsoft.OData.JsonLight.ODataJsonLightInputContext..ctor(ODataMessageInfo messageInfo, ODataMessageReaderSettings messageReaderSettings)\r\n at Microsoft.OData.Json.ODataJsonFormat.CreateInputContext(ODataMessageInfo messageInfo, ODataMessageReaderSettings messageReaderSettings)\r\n at Microsoft.OData.ODataMessageReader.ReadFromInput[T](Func`2 readFunc, ODataPayloadKind[] payloadKinds)\r\n at System.Web.OData.Formatter.Deserialization.ODataResourceDeserializer.Read(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext)\r\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)"}}'

Python Code

def upload_file_to_entity(url, attachment_data, version, file_name, entity_id, auth_token):
file_upload_url = f'{url}/api/data/{version}/annotations'

header_values = {
    'Authorization': auth_token,
    'Content-Type': 'application/json'
}

file_body = {
    'subject': 'Attachment Upload',
    'filename': file_name,
    'objectid_lead@odata.bind': f'/leads({entity_id})',
    'documentbody': attachment_data
}

file_upload_res = requests.post(file_upload_url, headers=header_values, data=file_body)
print(file_upload_res)
print(file_upload_res.content)


attachment_object = s3.get_object(Bucket=bucket_name, Key=attachment_file_location)
                attachment_data = attachment_object.get('Body').read()
                attachment_data_base64 = base64.b64encode(attachment_data) 
                base64_string = attachment_data_base64.decode('utf-8')



upload_file_to_entity(f'https://{org}.crm.dynamics.com',base64_string,'v9.2',file_name,lead_id,prm_auth_token)

Solution

  • Okay, I got it working.

    Everything is correct except for the json parameter in the request object. The correct request is as below

    file_upload_res = requests.post(file_upload_url, headers=header_values, json=file_body)