6
votes

I have multiple methods being called on different user actions which is using ClientContext. Creating it on every method execution was causing performance issue.

So I added it as static variable for re-usability, the performance improved with an average of 5seconds but then in some methods it start giving random issue of "Version conflict" on ExecuteQuery(). But if I remove the static and null check, then it get refreshed every time and performance becomes an issue

Is there any way to create one time object of this or at-least not on every call? And what is the default expiry of ClientContext?

Code for creating object of ClientContext:

    public class SPConnection
    {
    public static ClientContext SharepointClientContext { get; set; }
    public static ClientContext GetSharePointContext()
    {
        try
        {
            if (SharepointClientContext == null)
            {
                string appId = System.Configuration.ConfigurationManager.AppSettings["appId"];
                string appSecret = System.Configuration.ConfigurationManager.AppSettings["appSecret"];
                string siteUrl = System.Configuration.ConfigurationManager.AppSettings["siteUrl"];

                var authManager = new OfficeDevPnP.Core.AuthenticationManager();
                using (ClientContext clientContext = authManager.GetAppOnlyAuthenticatedContext(siteUrl, appId, appSecret))
                {
                    SharepointClientContext = clientContext;
                    return clientContext;
                }
            }
            else
                return SharepointClientContext;
        }
        catch (Exception ex)
        {
            iChange.Web.API.Authentication.SPConnection.InsertRecordToTableErrorLog("Mucebat:"+ex.Message, ex.StackTrace.ToString());
            throw ex;
        }

    }

Code for one of the method consuming it:

    public bool UpdateProfilePic(updateprofilepicmodel model)
    {
        using (ClientContext context = SPConnection.GetSharePointContext())
        {
            List list = context.Web.Lists.GetByTitle("Members");
            ListItemCreationInformation info = new ListItemCreationInformation();
            ListItem item = list.GetItemById(model.MemberId);

            item["ProfilePicture"] = model.ProfilepicUrl;
            item.Update();
            context.ExecuteQuery();
            return true;
        }

    }
3

3 Answers

1
votes

Can you try using ExecuteQueryAsync in combination with async tasks for performance improvement? e.g.

     public async Task <bool> UpdateProfilePic(updateprofilepicmodel model)
{
    using (ClientContext context = SPConnection.GetSharePointContext())
    {
        List list = context.Web.Lists.GetByTitle("Members");
        ListItem item = list.GetItemById(model.MemberId);
        context.Load(item);
        Task t1 = context.ExecuteQueryAsync();
        await t1.ContinueWith((t) =>
            {
                item["ProfilePicture"] = model.ProfilepicUrl;
                item.Update();
                Task t2 = context.ExecuteQueryAsync();
            });

        await t2.ContinueWith((t) =>
            {
               // do some stuff here if needed
            });

        return true;
    }
}

P.S: i have not tested this code, but in case if this works for you

0
votes

You can try to Load the list item before update it. Modify the code as below to check if it works.

public bool UpdateProfilePic(updateprofilepicmodel model)
{
    using (ClientContext context = SPConnection.GetSharePointContext())
    {
        List list = context.Web.Lists.GetByTitle("Members");
        ListItem item = list.GetItemById(model.MemberId);
        context.Load(item);
        context.ExecuteQuery();
        item["ProfilePicture"] = model.ProfilepicUrl;
        item.Update();
        context.ExecuteQuery();
        return true;
    }
}

If the code above not works, you can enable the version of the "Members" list in list settings to check if the issue still exists.

0
votes

You cannot use ClientContext as static object. In code you are writing your code in Using segment. ClientContext object will destroy once the execution of us using block is completed.