Question

Update Contact Profile Picture through odata.

Hi,

I am trying to make a php script to add thousands of pictures to existing contacts bpm.

Support helped me already and told that I should create (POST) a new entry in SysImageCollection with json {id: guid, name: guid}.

Then upload the image binary (base64, zipped or not, I tried them all) as an update (PUT) to SysImageCollection(guid'guid')/PreviewData.

Everything runs correct but I don't see any picture change in the contacts.

I use the guid of the contact in both steps.

Maybe I have to use a fresh guid and link that guid to the ContactCollection afterwards?

Does anyone have an idea what the json is to update the the profile picture for a contact?

Thanks in advance,

Kristof Leroux - Laranea

Like 0

Like

7 comments

It's hard to say how to create the integration on PHP. I created the functionality on c# and caught the requests with fiddler.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Xml;
using System.Xml.Linq;
 
namespace TransferImageViaOData
{
    class Program
    {
        // String of address bpm’online OData servise.
        private const string serverUri = "https://023148-crm-bundle.bpmonline.com/0/ServiceModel/EntityDataService.svc/";
        private const string authServiceUtri = "https://023148-crm-bundle.bpmonline.com/ServiceModel/AuthService.svc/Login";
 
        // Links to XML name spaces.
        private static readonly XNamespace ds = "http://schemas.microsoft.com/ado/2007/08/dataservices";
        private static readonly XNamespace dsmd = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
        private static readonly XNamespace atom = "http://www.w3.org/2005/Atom";
 
        private static readonly Guid ContactId = new Guid("410006e1-ca4e-4502-a9ec-e54d922d2c00");
 
        static void Main(string[] args)
        {
            var file = ReadFile("z:/2SupportLine/features.png");
            var id = CreateBpmEntityByOdataHttpExample();
            TransferImage(id, "Data", file);
            UpdateContactAvatar(id);
 
        }
 
        public static Guid CreateBpmEntityByOdataHttpExample()
        {
            Guid id = Guid.NewGuid();
            // Creating a xml message containing data on the created object.
            var content = new XElement(dsmd + "properties",
                          new XElement(ds + "Id", id.ToString()),
                          new XElement(ds + "HasRef", 0),
                          new XElement(ds + "MimeType", "image/png"),
                          new XElement(ds + "Name", "test1.png")
                          );
            var entry = new XElement(atom + "entry",
                        new XElement(atom + "content",
                        new XAttribute("type", "application/xml"), content));
            Console.WriteLine(entry.ToString());
            // Creating a request to the service which will add a new object to the contacts collection.
            var request = (HttpWebRequest)HttpWebRequest.Create(serverUri + "SysImageCollection/");
            request.Credentials = new NetworkCredential("Supervisor", "Supervisor");
            request.Method = "POST";
            request.Accept = "application/atom+xml";
            request.ContentType = "application/atom+xml;type=entry";
            // Recording the xml message to the request stream.
            using (var writer = XmlWriter.Create(request.GetRequestStream()))
            {
                entry.WriteTo(writer);
            }
            // Receiving a response from the service regarding the operation implementation result.
            using (WebResponse response = request.GetResponse())
            {
                if (((HttpWebResponse)response).StatusCode == HttpStatusCode.Created)
                {
                    // Processing the operation implementation result.
                }
            }
            return id;
        }
 
        public static void TransferImage(Guid fileRecordId, string columnName, byte[] file)
        {
            // Creating a request to the service which will add a new object to the contacts collection.
            var request = (HttpWebRequest)HttpWebRequest.Create(serverUri + "SysImageCollection(guid'" + fileRecordId.ToString() + "')/" + columnName);
            request.Credentials = new NetworkCredential("Supervisor", "Supervisor");
            request.Method = "PUT";
            request.Accept = "application/octet-stream,application/json;odata=verbose";
            request.ContentType = "multipart/form-data;boundary=+++++";
            // Recording the xml message to the request stream.
            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(file, 0, file.Length);
            }
            // Receiving a response from the service regarding the operation implementation result.
            using (WebResponse response = request.GetResponse())
            {
                if (((HttpWebResponse)response).StatusCode == HttpStatusCode.Created)
                {
                    // Processing the operation implementation result.
                }
            }
        }
 
        public static void UpdateContactAvatar(Guid fileRecordId)
        {
            var content = new XElement(dsmd + "properties",
                    new XElement(ds + "PhotoId", fileRecordId)
            );
            var entry = new XElement(atom + "entry",
                    new XElement(atom + "content",
                            new XAttribute("type", "application/xml"),
                            content)
                    );
            var request = (HttpWebRequest)HttpWebRequest.Create(serverUri
                    + "ContactCollection(guid'" + ContactId + "')");
            request.Credentials = new NetworkCredential("Supervisor", "Supervisor");
            // or request.Method = "MERGE";
            request.Method = "PUT";
            request.Accept = "application/atom+xml";
            request.ContentType = "application/atom+xml;type=entry";
            // Recording the xml message to the request stream.
            using (var writer = XmlWriter.Create(request.GetRequestStream()))
            {
                entry.WriteTo(writer);
            }
            // Receiving a response from the service regarding the operation implementation result.
            using (WebResponse response = request.GetResponse())
            {
                // Processing the operation implementation result.
            }
        }
 
        public static byte[] ReadFile(string filePath)
        {
            byte[] imageArray = System.IO.File.ReadAllBytes(filePath);
            return imageArray;
        }
    }
}

 

Please use the code below:

<?php

/*Please change this to you product name*/

define("baseUri", "https://023665-crm-bundle.bpmonline.com");

define("serverUri", baseUri . "/0/ServiceModel/EntityDataService.svc");

/*Please change this to you account setting*/

define("user", "Dmitro");

define("password", "123456789");

/*Please change this user_id to new user_id value for the user whose avatar needs to be changed*/

$user_id = 'c4ed336c-3e9b-40fe-8b82-5632476472b4';

/*Please change this file name*/

$file_name = 'test_img.png';

$file_id = CreateBpmEntityFile($file_name);

TransferImage($file_id, $file_name);

UpdateContactAvatar($user_id, $file_id);

function CreateBpmEntityFile($file_name) {

    $headers = [

      'Accept: application/atom+xml',

      'Content-Type: application/atom+xml;type=entry',

      "Authorization: Basic " . base64_encode(user . ':' . password),

      'Expect: 100-continue',

    ];

    $uid = GetUid();

    $postData = <<<XML

<?xml version="1.0" encoding="utf-8"?><entry xmlns="http://www.w3.org/2005/Atom"><content type="application/xml"><properties xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><Id xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">$uid</Id><HasRef xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">0</HasRef><MimeType xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">image/png</MimeType><Name xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">$file_name</Name></properties></content></entry>

XML;

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, serverUri . "/SysImageCollection/");

    curl_setopt($ch, CURLOPT_POST, 1);

    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

    curl_exec($ch);

    curl_close($ch);

    return $uid;

}

function TransferImage($id, $file_name) {

    $fh_res = fopen($file_name, 'r');

    $xml_data = fread($fh_res, filesize($file_name));

    $headers = [

      "Accept: application/octet-stream,application/json;odata=verbose",

      "Content-type: multipart/form-data;boundary=+++++",

      "Authorization: Basic " . base64_encode(user . ':' . password),

      "Expect: 100-continue",

    ];

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, serverUri . "/SysImageCollection(guid'$id')/Data");

    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);

    curl_setopt($ch, CURLOPT_BINARYTRANSFER, TRUE);

    curl_setopt($ch, CURLOPT_POST, TRUE);

    curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_data);

    curl_exec($ch);

    fclose($fh_res);

}

function UpdateContactAvatar($user_id, $file_id) {

    $headers = [

      'Accept: application/atom+xml',

      'Content-Type: application/atom+xml;type=entry',

      "Authorization: Basic " . base64_encode(user . ':' . password),

    ];

    $postData = <<<XML

<?xml version="1.0" encoding="utf-8"?><entry xmlns="http://www.w3.org/2005/Atom"><content type="application/xml"><properties xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><PhotoId xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">$file_id</PhotoId></properties></content></entry> 

XML;

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, serverUri . "/ContactCollection(guid'$user_id')");

    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);

    curl_setopt($ch, CURLOPT_BINARYTRANSFER, TRUE);

    curl_setopt($ch, CURLOPT_POST, TRUE);

    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);

    curl_exec($ch);

    curl_close($ch);

}

/**

 * Generate uniq id

 *

 * @return string

 */

function GetUid() {

    $uid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',

      mt_rand(0, 0xffff), mt_rand(0, 0xffff),

      mt_rand(0, 0xffff),

      mt_rand(0, 0x0fff) | 0x4000,

      mt_rand(0, 0x3fff) | 0x8000,

      mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));

    return $uid;

}

 

Mark Bailey,

Thanks Mark for your solution. It is working but I need to use it as a service and my implementation goes like::

 

// Endpoint

        [OperationContract]

        [WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,

        ResponseFormat = WebMessageFormat.Json)]

        public string UploadContactPicture(Data data)

        {

            CifNoVar = data.CIFNo;

            ContactId = Guid.Parse(GetContactIdByCIF(data.CIFNo));

            var file = ReadFile(data.Image);

            var id = CreateBpmEntityByOdataHttpExample();

            TransferImage(id, "Data", file);

            UpdateContactAvatar(id);

            return ContactId.ToString();

        }

 

where Data is::

[DataContract]

    public class Data

    {

        [DataMember]

        public string CIFNo { get; set; }

        [DataMember]

        public string Image { get; set; }

    }

 

The UploadContactPicture is working well to upload a contact picture when my implementation is::

 

[OperationContract]

        [WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,

        ResponseFormat = WebMessageFormat.Json)]

        public string UploadContactPicture(string CIFNo)

        {

            CifNoVar = CIFNo;

            ContactId = Guid.Parse(GetContactIdByCIF(CIFNo));

            var file = ReadFile("E:/SBL_QA/Terrasoft.WebApp/conf/content/img/OBSWConsultationPanelSchema-DefaultContactPhoto.jpg");

            var id = CreateBpmEntityByOdataHttpExample();

            TransferImage(id, "Data", file);

            UpdateContactAvatar(id);

            return ContactId.ToString();

        }

 How can I use a JSON object(Model object) as a parameter to the UploadContactPicture method to successfully upload a picture as shown in the example above. 

Dear,

In order to resolve the issue please use the article by the link below:

 

https://stackoverflow.com/questions/52489002/get-the-object-is-null-using-json-in-wcf-service/52497740#52497740

 

Best regards,

Norton

Norton Lingard,

Hi Norton, thanks for your reply. I had tried it, but it didn't work. It says::

403 - Forbidden: Access is denied. You do not have permission to view this directory or page using the credentials that you supplied.

This is my full implementation::

namespace Terrasoft.Configuration.SBLCustomNamespace

{

    using System;

    using System.ServiceModel;

    using System.ServiceModel.Web;

    using System.ServiceModel.Activation;

    using Terrasoft.Core;

    using Terrasoft.Web.Common;

    using Terrasoft.Core.Entities; 

    using Terrasoft.Core.DB;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.IO;

    using System.Linq;

    using System.Net;

    using System.Xml;

    using System.Xml.Linq;

    using System.Web.Hosting;

    using System.Runtime.Serialization;

    

    [DataContract]

    public class Data

    {

        [DataMember]

        public string CIFNo { get; set; }

        [DataMember]

        public string Image { get; set; }

    }

    [ServiceContract]

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

    public class SBLContactPictureUploaderService: BaseService

    {

        // Link to the UserConnection instance required to access the database.

        private SystemUserConnection _systemUserConnection;

        private SystemUserConnection SystemUserConnection {

            get {

                return _systemUserConnection ?? (_systemUserConnection = (SystemUserConnection)AppConnection.SystemUserConnection);

            }

        }

        

        // String of address bpm’online OData service.

        private const string serverUri = "https://qacrm.siddharthabank.com/0/ServiceModel/EntityDataService.svc/";

        private const string authServiceUtri = "https://qacrm.siddharthabank.com/ServiceModel/AuthService.svc/Login";

 

        // Links to XML name spaces.

        private readonly XNamespace ds = "http://schemas.microsoft.com/ado/2007/08/dataservices";

        private readonly XNamespace dsmd = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";

        private readonly XNamespace atom = "http://www.w3.org/2005/Atom";

 

        private Guid ContactId = Guid.NewGuid();

        

        private string CifNoVar = string.Empty;

 

         // A method that returns the contact's ID by its name.

        [OperationContract]

        [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare,

        ResponseFormat = WebMessageFormat.Json)]

        public string UploadContactPicture(Data data)

        {

            CifNoVar = data.CIFNo;

            ContactId = Guid.Parse(GetContactIdByCIF(data.CIFNo));

            var file = ReadFile(data.Image);

            var id = CreateBpmEntityByOdataHttpExample();

            TransferImage(id, "Data", file);

            UpdateContactAvatar(id);

            return ContactId.ToString();

        }

        

        public Guid CreateBpmEntityByOdataHttpExample()

        {

            Guid id = Guid.NewGuid();

            // Creating a xml message containing data on the created object.

            var content = new XElement(dsmd + "properties",

                          new XElement(ds + "Id", id.ToString()),

                          new XElement(ds + "HasRef", 0),

                          new XElement(ds + "MimeType", "image/jpg"),

                          new XElement(ds + "Name", CifNoVar.ToString().Trim()+".jpg")

                          );

            var entry = new XElement(atom + "entry",

                        new XElement(atom + "content",

                        new XAttribute("type", "application/xml"), content));

            Console.WriteLine(entry.ToString());

            // Creating a request to the service which will add a new object to the contacts collection.

            var request = (HttpWebRequest)HttpWebRequest.Create(serverUri + "SysImageCollection/");

            request.Credentials = new NetworkCredential("Supervisor", "Supervis0r@1234%");

            request.Method = "POST";

            request.Accept = "application/atom+xml";

            request.ContentType = "application/atom+xml;type=entry";

            // Recording the xml message to the request stream.

            using (var writer = XmlWriter.Create(request.GetRequestStream()))

            {

                entry.WriteTo(writer);

            }

            // Receiving a response from the service regarding the operation implementation result.

            using (WebResponse response = request.GetResponse())

            {

                if (((HttpWebResponse)response).StatusCode == HttpStatusCode.Created)

                {

                    // Processing the operation implementation result.

                }

            }

            return id;

        }

 

        public void TransferImage(Guid fileRecordId, string columnName, byte[] file)

        {

            // Creating a request to the service which will add a new object to the contacts collection.

            var request = (HttpWebRequest)HttpWebRequest.Create(serverUri + "SysImageCollection(guid'" + fileRecordId.ToString() + "')/" + columnName);

            request.Credentials = new NetworkCredential("Supervisor", "Supervis0r@1234%");

            request.Method = "PUT";

            request.Accept = "application/octet-stream,application/json;odata=verbose";

            request.ContentType = "multipart/form-data;boundary=+++++";

            // Recording the xml message to the request stream.

            using (Stream requestStream = request.GetRequestStream())

            {

                requestStream.Write(file, 0, file.Length);

            }

            // Receiving a response from the service regarding the operation implementation result.

            using (WebResponse response = request.GetResponse())

            {

                if (((HttpWebResponse)response).StatusCode == HttpStatusCode.Created)

                {

                    // Processing the operation implementation result.

                }

            }

        }

 

        public void UpdateContactAvatar(Guid fileRecordId)

        {

            var content = new XElement(dsmd + "properties",

                    new XElement(ds + "PhotoId", fileRecordId)

            );

            var entry = new XElement(atom + "entry",

                    new XElement(atom + "content",

                            new XAttribute("type", "application/xml"),

                            content)

                    );

            var request = (HttpWebRequest)HttpWebRequest.Create(serverUri

                    + "ContactCollection(guid'" + ContactId + "')");

            request.Credentials = new NetworkCredential("Supervisor", "Supervis0r@1234%");

            // or request.Method = "MERGE";

            request.Method = "PUT";

            request.Accept = "application/atom+xml";

            request.ContentType = "application/atom+xml;type=entry";

            // Recording the xml message to the request stream.

            using (var writer = XmlWriter.Create(request.GetRequestStream()))

            {

                entry.WriteTo(writer);

            }

            // Receiving a response from the service regarding the operation implementation result.

            using (WebResponse response = request.GetResponse())

            {

                // Processing the operation implementation result.

            }

        }

 

        public static byte[] ReadFile(string filePath)

        {

            byte[] imageArray = System.IO.File.ReadAllBytes(filePath);

            return imageArray;

        }

        

        // A method that returns the contact's ID by its name.

        [OperationContract]

        [WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,

        ResponseFormat = WebMessageFormat.Json)]

        public string GetContactIdByName(string Name){

            // The default result.

            var result = "";

            // An EntitySchemaQuery instance that accesses the Contact table of the database.

            var esq = new EntitySchemaQuery(SystemUserConnection.EntitySchemaManager, "Contact");

            // Adding columns to the query.

            var colId = esq.AddColumn("Id");

            var colName = esq.AddColumn("Name");

            // Filter the query data.

            var esqFilter = esq.CreateFilterWithParameters(FilterComparisonType.Equal, "Name", Name);

            esq.Filters.Add(esqFilter);

            // Get the result of the query.

            var entities = esq.GetEntityCollection(SystemUserConnection);

            // If the data is received.

            if (entities.Count > 0)

            {

                // Return the value of the "Id" column of the first record of the query result.

                result = entities[0].GetColumnValue(colId.Name).ToString();

                // You can also use this option:

                // result = entities [0]. GetTypedColumnValue <string> (colId.Name);

            }

            // Return the result.

            return result;

        }

        

        public string GetContactIdByCIF(string CIFNo){

            // The default result.

            var result = "";

            // An EntitySchemaQuery instance that accesses the Contact table of the database.

            var esq = new EntitySchemaQuery(SystemUserConnection.EntitySchemaManager, "Contact");

            // Adding columns to the query.

            var colId = esq.AddColumn("Id");

            var colName = esq.AddColumn("SBLCIF");

            // Filter the query data.

            var esqFilter = esq.CreateFilterWithParameters(FilterComparisonType.Equal, "SBLCIF", CIFNo);

            esq.Filters.Add(esqFilter);

            // Get the result of the query.

            var entities = esq.GetEntityCollection(SystemUserConnection);

            // If the data is received.

            if (entities.Count > 0)

            {

                // Return the value of the "Id" column of the first record of the query result.

                result = entities[0].GetColumnValue(colId.Name).ToString();

                // You can also use this option:

                // result = entities [0]. GetTypedColumnValue <string> (colId.Name);

            }

            // Return the result.

            return result;

        }

        

        [OperationContract]

        [WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,

        ResponseFormat = WebMessageFormat.Json)]

        public string InsertContact(string contactName)

        {

            contactName = contactName ?? "Unknown contact";

            var ins = new Insert(UserConnection)

                .Into("Contact")

                .Set("Name", Column.Const(contactName));

            var affectedRows = ins.Execute();

            var result = $"Inserted new contact with name '{contactName}'. {affectedRows} rows affected";

            return result;

        }

    }

}

 

Dear,

 

In order to resolve the issue please use the article by the link below:

 

https://community.creatio.com/questions/403-forbidden-when-using-post-custom-service

 

Best regards,

Norton

Show all comments