web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

News and Announcements icon
Community site session details

Community site session details

Session Id :
Power Platform Community / Forums / Power Pages / Power Apps Portal Prof...
Power Pages
Answered

Power Apps Portal Profile Picture

(3) ShareShare
ReportReport
Posted on by 20

As we all know by now, Power Apps Portals profile pictures are not yet an OOB feature. In the past, I have followed custom solutions posted by others that were very JavaScript heavy and not all that clean. Additionally, when these solutions are implemented in a portal used by thousands of people, the massive amounts of web files that get created drastically slow down portal speed as it tries to pre-load all of these graphics (whose parent pages were set to 'Home'). Additionally, these web files were not associated with the actual portal contact records. Lastly, when a user uploaded a new image, they would not see it on their profile until the next time the portal automatically refreshed its cache.

 

So I implemented a cleaner solution (in my opinion). I created a new entity form that used the OOB 'Profile Web Form' and set up note attachments (along with the necessary entity permissions for contact(self) and notes(parent)). I then created a custom web template and copied the code from the 'Page with Side Navigation (2 columns)' web template into it.

 

I then added another block to the template and included a line for my custom profile entity form:

 

{% block rightside %}
 {% entityform name:'Profile' %}
{% endblock %}

 

 

Then I created another custom web template for retrieving the most recently uploaded jpeg attachment (but you can add in the ability for other image types if you need) associated to the logged in contact's record:

 

{% fetchxml profilepicfetchxml %}
<fetch version='1.0' output-format='xml-platform' mapping='logical'>
 <entity name="contact">
 <attribute name="contactid" />
 <filter type="and">
 <condition attribute="contactid" operator="eq" value="{{ user.id }}" />
 </filter>
 <link-entity name="annotation" from="objectid" to="contactid" link-type="inner" alias="note">
 <attribute name='filename' />
 <attribute name='notetext' />
 <attribute name='annotationid' />
 <attribute name='documentbody' />
 <order attribute="createdon" descending="true" />
 <filter type='or' >
 <condition attribute='mimetype' operator='eq' value='image/jpeg' />
 </filter>
 </link-entity>
 </entity>
</fetch>
{% endfetchxml %}

 

 

I added an include reference for this in the profile web template, and then added a new div to display the top result's document body as a base64 jpeg. So this is what the finished web template looks like:

 

{% extends "layout_2_column_wide_right" %}

{% block aside %}
 {% include "anc_profile_picture_fetch" %}
 <div style="position:relative">
 <div id="profile-pic" onclick="$('#AttachFile').click();$('#confirm-upload').show();$('#pic').css('opacity',.3);" style="cursor:pointer;">
 {% if profilepicfetchxml.results.entities.size > 0 %}
 <img src="data&colon;image/jpeg;base64,{{ profilepicfetchxml.results.entities[0]['note.documentbody'] }}" style="width: 100%; height: auto;" id="pic">
 {% else %}
 <img src="~/profile/default-profile.jpg" style="width: 100%; height: auto;" id="pic">
 {% endif %}
 </div>
 <button class="btn btn-success" type="button" onclick="$('#UpdateButton').click();" id="confirm-upload" style="display:none;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);">Confirm Upload</button>
 </div>
 <div class="hidden-xs hidden-print">
 {% include "side_navigation" depth_offset: 1 %}
 </div>
{% endblock %}
{% block rightside %}
 {% entityform name:'Profile' %}
{% endblock %}

 

 

You will notice I also have a default picture (saved as a web file) that displays if no results are found through fetch. I also added a custom upload confirmation button that appears over the profile picture when it is clicked. This button simply triggers a click event on the profile form's submit button. On the Profile web page, I added a CSS rule to hide the attach file option so users only click on the image to open their file explorer (as well as some styling for the navigation pane):

 

.file-cell {
 display: none !important;
}
.side-nav li ul li {
 position: relative;
 display: block;
 padding: .5rem 1rem;
 text-decoration: none;
 background-color: #fff;
 border: 1px solid rgba(0,0,0,.125);
}

 

 

Lastly, to allow users to preview their image selection, I added the following Javascript&colon;

 

function readURL(input) {
 if (input.files && input.files[0]) {
 var reader = new FileReader();
 
 reader.onload = function(e) {
 $('#pic').attr('src', e.target.result);
 }
 
 reader.readAsDataURL(input.files[0]); // convert to base64 string
 }
}

$("#AttachFile").change(function() {
 readURL(this);
});

 

 

Overall, this solution works much better than ones we have seen/used in the past and avoids the issue of slower portal load times (changes to profile pictures are also instant with this solution).

 

Here is what our custom profile page looks like with the default image:

Picture1.png

Here is a plugin I also wrote to automatically set the contact record's entity image to the uploaded picture from portal (on create of annotation):

 

using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;

namespace CustomPlugins
{
 public class SetProfilePicture : Plugin
 {
 private readonly string postImageAlias = "postImage";
 public SetProfilePicture() : base(typeof(SetProfilePicture))
 {
 base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(40, "Create", "annotation", new Action<LocalPluginContext>(ExecuteSetProfilePicture)));
 }
 protected void ExecuteSetProfilePicture(LocalPluginContext localContext)
 {
 if (localContext == null)
 {
 throw new ArgumentNullException("localContext");
 }

 IPluginExecutionContext context = localContext.PluginExecutionContext;
 IOrganizationService orgService = localContext.OrganizationService;
 ITracingService tracingService = localContext.TracingService;

 Entity postImageEntity = (context.PostEntityImages != null && context.PostEntityImages.Contains(this.postImageAlias)) ? context.PostEntityImages[this.postImageAlias] : null;
 string documentbody = postImageEntity.Attributes.Contains("documentbody") ? postImageEntity.Attributes["documentbody"].ToString() : "";
 
 if ((context.Depth <= 1) && context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
 {
 Entity note = (Entity)context.InputParameters["Target"];

 string fetch = String.Format(@"
 <fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
 <entity name='annotation'>
 <attribute name='annotationid' />
 <filter type='and'>
 <condition attribute='annotationid' operator='eq' value='{0}' />
 </filter>
 <link-entity name='contact' from='contactid' to='objectid' link-type='inner' alias='contact'>
 <attribute name='contactid' />
 </link-entity>
 </entity>
 </fetch>", note.Id);

 EntityCollection result = orgService.RetrieveMultiple(new FetchExpression(fetch));

 if (result.Entities.Count > 0)
 {
 Entity contact = new Entity("contact", Guid.Parse(result.Entities[0].GetAttributeValue<AliasedValue>("contact.contactid").Value.ToString()));
 contact["entityimage"] = Convert.FromBase64String(documentbody);
 orgService.Update(contact);
 }
 }
 }
 }
}

 

Please feel free to comment with any suggestions/feedback.

Categories:
I have the same question (0)
  • lthomas927 Profile Picture
    20 on at

    Sorry, forgot to mention. I created a new Page Template that used our custom Web Template and switched the Profile web page to use this new Page Template 🙂

  • ragavanrajan Profile Picture
    7,044 Most Valuable Professional on at

    Great work @lthomas927  🙂 very useful 

  • Verified answer
    lthomas927 Profile Picture
    20 on at

    Edit: Added plugin code

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Introducing the 2026 Season 1 community Super Users

Congratulations to our 2026 Super Users!

Kudos to our 2025 Community Spotlight Honorees

Congratulations to our 2025 community superstars!

Congratulations to the March Top 10 Community Leaders!

These are the community rock stars!

Leaderboard > Power Pages

#1
DP_Prabh Profile Picture

DP_Prabh 41

#2
oliver.rodrigues Profile Picture

oliver.rodrigues 35 Most Valuable Professional

#3
rezarizvii Profile Picture

rezarizvii 28

Last 30 days Overall leaderboard