Unified Service Desk – Create Sessions from Custom hosted control

Hi,

To create a customer from type of custom hosted control, You need to inherit the interface IContextManager.

Oncee you implement it, It should give you few methods which will be needful if you are working with sessions.

  • GenerateSessionName // This will generate the session name , Put your logic here
  • RenewSession
  • SetContext // sets the context of session

Have the below method. callRefid is used to give the reference of caller in case of CTI.

private Session OpenSession(CustomerEntity customer, Guid callRefId)
{
try
{
return this.desktopAccess.OpenSession(customer, callRefId);
}
catch (SessionLimitExceededException ex)
{
// Logging.Error(productName, ex.Message);
return null;
}
}

Create a dynamic customer ecord and call session open method

var cust = new DynamicsCustomerRecord(new EntityDescription { Id = contactId, LogicalName = “contact” });
cust.SessionName = customerFromCrm.FullName;
CustomerEntity sessionCustomer = null;
sessionCustomer = new CustomerEntity(contactId.ToString(), cust, “<CustomerID>1<CustomerID/>”, false, this.ApplicationName);

sessionCustomer.IsNewCustomer = true;

// Start a new session
OpenSession(sessionCustomer, Guid.Empty);

This will open the sessions for customers. From there you can open your web applications in that session.

Happy coding…!

Sreeni

Advertisement

Published by Sreeni Pavalla

Working as a Assistant Technical Manager in Positive Edge Technologies. Having over 11 years of extensive hands-on experience in MS Dynamics CRM 4.0, 2011, 2013, 2015, 2016, Dynamics 365 with over 5 years of experience in CRM Online. You can visit my blog here https://sreenipavalla.me/

20 thoughts on “Unified Service Desk – Create Sessions from Custom hosted control

  1. Hi Sreeni,

    I’m currently working on USD, and my requirement is to create custom search control. I had developed WPF Hosted control to search customer in CRM and able to generate list of searched customers.

    Now, when i’m trying to open the customer in new session I am not able to open it. I am using the same code which you mention in your above post ,but still not able to figure out what went wrong in my code block.

    Could you please help me to resolve this issue. Your help is highly appreciated.

    Thank you.

    Regards,
    Atul

    Like

  2. Hi Sreeni,

    I’m currently working on USD, and my requirement is to create custom search control. I had developed WPF Hosted control to search customer in CRM and able to generate list of searched customers.

    Now, when i’m trying to open the customer in new session I am not able to open it. I am using the same code which you mention in your above post ,but still not able to figure out what went wrong in my code block.

    Could you please help me to resolve this issue. Your help is highly appreciated.

    Thank you.

    Regards,
    Atul

    Like

  3. Hi Sreeni,

    Thank you for your response.

    I have inherited IContextManager interface , it gives me 4 methods –
    1. SetContext – In this method i’m setting few values in context like CUSTOMERID,INITIALENTITY
    etc.
    2. GenerateSessionName – In this method i’m generating session name as string.
    3. RenewSession – Here i’m setting ‘LocalSessionManager.ActiveSession.Name’ name which is
    same as the session name from GenerateSessionName method.
    4. DesktopContextChange – In this method I have created the object of AgentDesktopSession as
    “AgentDesktopSession Session = (AgentDesktopSession)LocalSessionManager.ActiveSession”
    and allocated few values like
    Session.Customer.CustomerId = context[ContextVar.CUSTOMERID];
    Session.Customer.DesktopCustomer = custRec; where “custRec” is DynamicsCustomerRecord
    object.

    Now, to open session I have created CustomerEntity object as –
    customer = new CustomerEntity(cust.CustomerId, cust, “1”, false, this.ApplicationName);

    In this “cust” is nothing but the “DynamicsCustomerRecord” object. and after just called the openSession method OpenSession(customer, Guid.Empty);

    The issue with opening the customer record only, I am able to open new session with appropriate name, but the customer record will not getting populated.

    I hope this will explain my issue.

    Regards,
    Atul

    Like

  4. Hi,

    You are just opening a session, It doesnot mean that it will open some record for you. You should specify which record to open after opening a session ,

    FireRequestAction(new RequestActionEventArgs(“HostedContro”, “Action Name”, “Parameters”));

    or you can create action on Session Creation, Which will always open after every new session created.

    Like

  5. Hi Sreeni,

    I am still not able to open customer record along with session, I am stuck in this very badly.
    Could you please help me and provide some sample for how to open record from custom hosted control in USD.

    Thanks,
    Atul

    Liked by 1 person

  6. Hi Sreeni,
    I am also facing the same issue which is same as atul.
    I have tried with
    FireRequestAction(new RequestActionEventArgs(“CIS”, “New_CRM-Page”, “null”));

    but still session is not opened.

    I am badly struggling this issue since 10 days.. please help me out.

    Like

  7. Hi Sreeni,

    I sent the code via Gmail.. I am using the Online instance to teast application. Helper class i have mentions the Online trail version details as well.
    Thanks in Advance. if don’t mind give me your Mobile number..

    Like

  8. Hey,

    I have alooked into your code.

    I dont see that you are creating a dynamiccustomerRecord.

    This is how your doSearch should be

    public void DoSearch(CustomerEntity customer)
    {
    // Start a session

    var cust = new DynamicsCustomerRecord(new EntityDescription { Id = customer.CustomerId, LogicalName = “contact” });
    cust.SessionName = customer.FullName;
    CustomerEntity sessionCustomer = null;
    sessionCustomer = new CustomerEntity(customer.CustomerId.ToString(), cust, “1”, false, this.ApplicationName);

    sessionCustomer.IsNewCustomer = true;
    OpenSession(customer, Guid.Empty);
    //Before request action check for control existed or not
    FireRequestAction(new RequestActionEventArgs(“CIS”, “New_CRM-Page”, null));
    }

    // Add you fire
    that is the reason it is not opening anything.

    Did you get a chance to debug it? Are you getting customer record correctly?

    Thank you,
    Sreeni

    Like

  9. Hi Sreeni,

    I have debug it.. but no luck session is opening without contact record.

    Please find the my code
    public Context SetContext(CustomerEntity customer)
    {
    try
    {
    string temp = Context.GetContext();
    Context context = new Context(temp);
    if (customer != null)
    {
    DynamicsCustomerRecord custRec = null;
    if (customer.DesktopCustomer is DynamicsCustomerRecord)
    custRec = (DynamicsCustomerRecord)customer.DesktopCustomer;
    else
    {
    System.Diagnostics.Trace.WriteLine(string.Format(CultureInfo.CurrentUICulture, IPF.CRM.CustomerInformationSystem.Properties.Resources.SETCONTEXTERROR,
    this.Name, typeof(DynamicsCustomerRecord).ToString()));
    return context;
    }

    if (custRec != null)
    {
    customer.IsNewCustomer = false; // Reset the flag if it was set.
    context[“NewCaseUrl”] = createNewCaseUrl(context);

    }
    }
    return context;
    }
    catch (Exception)
    {
    throw;
    }
    }

    ///
    ///
    ///
    /// From whose context the values needs to get.
    /// Returns the new case url
    public string createNewCaseUrl(Context context)
    {
    string caseUrl = string.Empty;
    string queryString = string.Empty;

    if (!Convert.ToBoolean(context[ContextVar.ISNEWCUSTOMER]))
    {
    string extraqs = “customerid=” + context[ContextVar.CUSTOMERID] + “”;
    extraqs = extraqs + “&customeridname=”;
    extraqs = extraqs + context[ContextVar.CUSTOMERNAME];
    extraqs = extraqs + “&customeridtype=” + context[ContextVar.CUSTOMERTYPE];
    extraqs = HttpUtility.UrlEncode(extraqs);
    queryString = @”/main.aspx?etc=112&pagetype=entityrecord&newWindow=true&extraqs=” + extraqs;
    }
    else
    {
    queryString = @”/main.aspx?etc=112&pagetype=entityrecord&newWindow=true”;
    }

    // this.FireRequestAction(new RequestActionEventArgs(“CIO”, “New_CRM_Page”, null));
    this.FireRequestAction(new RequestActionEventArgs(“CIO”, “New_CRM_Page”, “contact”)); 
    caseUrl = “https://rammohan.api.crm5.dynamics.com” + queryString;

    return caseUrl;
    }

    public string GenerateSessionName(CustomerEntity customer)
    {
    string sSessionName = string.Empty;
    if (customer != null)
    {
    CustomerRecord custRec = null;
    if (customer.DesktopCustomer is CustomerRecord)
    custRec = (CustomerRecord)customer.DesktopCustomer;
    else
    {
    System.Diagnostics.Trace.WriteLine(string.Format(CultureInfo.CurrentUICulture,
    IPF.CRM.CustomerInformationSystem.Properties.Resources.GENERATE_SESSIONNAME_ERROR,
    this.Name, typeof(CustomerRecord).ToString()));
    return sSessionName;
    }

    }

    return sSessionName;
    }

    ///
    /// Called by the desktop to determin and update some session level items
    /// if returns true, a Renew Session Event is raised in the desktop. Warning: this is a UI effecting event.
    ///
    /// New Context
    /// True to Reload the Session, False to not.
    public bool RenewSession(Context context)
    {
    //try
    //{
    // // Check to see if the session Name changed between the old context and new context..
    // // Generate session name from context;
    // string sContextSessionName = null;
    // if (context[ContextVar.CUSTOMERTYPE].Equals(“contact”, StringComparison.Ordinal))
    // {
    // sContextSessionName = string.Format(CultureInfo.CurrentUICulture, “{0} {1}”,
    // context[ContextVar.CUSTOMERFIRSTNAME],
    // context[ContextVar.CUSTOMERLASTNAME]
    // ).Trim();
    // }
    // else
    // {
    // sContextSessionName = context[ContextVar.ACCOUNTNAME].Trim();
    // }

    // if (!LocalSessionManager.ActiveSession.Global || !string.IsNullOrEmpty(LocalSessionManager.ActiveSession.Name))
    // if (!LocalSessionManager.ActiveSession.Name.Equals(sContextSessionName, StringComparison.CurrentCultureIgnoreCase))
    // {
    // // Session name changed..
    // LocalSessionManager.ActiveSession.Name = sContextSessionName;
    // return true;
    // }
    // return false;
    //}
    //catch (Exception ex)
    //{
    // System.Diagnostics.Trace.WriteLine(IPF.CRM.CustomerInformationSystem.Properties.Resources.RENEWSESSION_EXCEPTION + ex.Message);
    // throw;
    //}
    return false;
    }

    public bool DesktopContextChange(Context context)
    {
    try
    {
    AgentDesktopSession Session = (AgentDesktopSession)LocalSessionManager.ActiveSession;
    if (Session.Customer != null)
    {
    //CustomerRecord custRec = (CustomerRecord)Session.Customer.DesktopCustomer;
    DynamicsCustomerRecord custRec = (DynamicsCustomerRecord)Session.Customer.DesktopCustomer;
    if (null == custRec)
    custRec = new DynamicsCustomerRecord();
    Session.Customer.CustomerId = context[ContextVar.CUSTOMERID];

    Session.Customer.DesktopCustomer = custRec;
    }
    return true;
    }
    catch (Exception)
    {
    throw;
    }
    }

    #endregion

    #region ICustomerSearch Members

    public bool DisplayInQuickAccessSearchList
    {
    get { return true; }
    }

    public string QuickAccessSearchElementText
    {
    get { return “Sample Employee Search”; }
    }

    public void DoSearch(CustomerEntity customer)
    {
    // Start a session
    var cust = new DynamicsCustomerRecord(new EntityDescription
    {
    Id = new Guid(customer.CustomerId),
    LogicalName =”contact”
    });
    cust.SessionName = “my customer”;
    CustomerEntity sessionCustomer = null;
    sessionCustomer = new CustomerEntity(customer.CustomerId.ToString(), cust, “1”, false, this.ApplicationName);

    sessionCustomer.IsNewCustomer = true;
    OpenSession(customer, Guid.Empty);
    //Before request action check for control existed or not
    FireRequestAction(new RequestActionEventArgs(“CIS”, “New_CRM_Page”, null));
    }

    protected override void DoAction(RequestActionEventArgs args)
    {
    if (args.Action.Equals(CtiLookupRequest.CTILOOKUPACTIONNAME, StringComparison.Ordinal))
    {
    // Process request coming from the CTI Desktop Manager
    DoSearchFromCtiRequest(args.Data);
    }
    else
    {
    if (args.Action.Equals(“StartSessionFromQueue”, StringComparison.Ordinal))
    {
    DoSearchFromQueue(args.Data);
    }
    else
    {
    base.DoAction(args);
    }
    }
    }

    public void DoSearch(CustomerRecord data)
    {

    bool isNewCustomer = false;
    CustomerEntity customer = null;

    //

    if (data != null)
    {
    //DynamicsCustomerRecord cus = new DynamicsCustomerRecord();
    var cus = new DynamicsCustomerRecord(new EntityDescription
    {
    Id = new Guid(data.CustomerId),
    LogicalName = “contact”
    });
    cus.SessionName = “my customer”;

    customer = new CustomerEntity(cus.CustomerId, cus, “1”, false, this.ApplicationName);
    }
    else
    {

    isNewCustomer = true;
    Result = CreateCustomer();
    var cus = new DynamicsCustomerRecord(new EntityDescription
    {
    Id = new Guid(Result.CustomerId),
    LogicalName = “contact”
    });
    cus.SessionName = “my customer”;
    customer = new CustomerEntity(cus.CustomerId, cus, “1”, false, this.ApplicationName) { IsNewCustomer = true };
    }

    // Explicitly setting the IsNewCustomer flag to true because one of CustomerSearchResult event subscribers is resetting it to false.
    if (isNewCustomer)
    {
    customer.IsNewCustomer = true;
    }

    // Start a new session
    //that informatioj
    OpenSession(customer, Guid.Empty);
    FireRequestAction(new RequestActionEventArgs(“CIO”, “New_CRM_Page”, null));
    }

    public void Search(CustomerRecord data)
    {

    bool isNewCustomer = false;
    CustomerEntity customer = null;
    if (data != null)
    {
    customer = new CustomerEntity(data.CustomerId, data, GeneralFunctions.Serialize (data) , false, this.ApplicationName);
    }
    else
    {
    isNewCustomer = true;
    data = CreateCustomer();
    customer = new CustomerEntity(data.CustomerId, data, “1”, false, this.ApplicationName) { IsNewCustomer = true };
    }

    // Explicitly setting the IsNewCustomer flag to true because one of CustomerSearchResult event subscribers is resetting it to false.
    if (isNewCustomer)
    {
    customer.IsNewCustomer = true;
    }

    // Start a new session
    OpenSession(customer, new Guid( data.CustomerId));
    //FireRequestAction(new RequestActionEventArgs(“Customer Search”, “OpenCustomerRecord”, “www.bing.com”));
    }

    ///
    /// This method is used by the CTI system to handle a specialized CTI lookup request
    ///
    /// Search Paramaters

    private void BuildCustomerResponse(string custId, CustomerRecord customSearchRecord, bool isNewCust, Guid callRefId)
    {
    // This is the Uii Customer Record that is attached to the session that is about to be created.
    CustomerEntity UiiCustomerRecord = new CustomerEntity(custId, customSearchRecord,
    GeneralFunctions.Serialize(customSearchRecord), isNewCust, this.ApplicationName);

    // Start a new session
    OpenSession(UiiCustomerRecord, callRefId);
    }

    private void DoSearchFromQueue(string customerData)
    {
    //Parse the action Data to get the Guid from the URL
    var customerService = AifServiceContainer.Instance.GetService();

    if (customerService != null && !String.IsNullOrEmpty(customerData))
    {
    CustomerRecord newCustomer = oHelper.GetCustomerByCaseId(new Guid(customerData));
    if (newCustomer != null)
    DoSearch(new CustomerEntity(newCustomer.CustomerId, newCustomer, “1”, false, this.ApplicationName));
    }
    }

    private Session OpenSession(CustomerEntity customer, Guid callRefId)
    {
    try
    {
    return desktopAccess.OpenSession(customer, callRefId);
    }
    catch (SessionLimitExceededException ex)
    {
    Logging.Error(productName, ex.Message);
    return null;
    }
    }

    ///
    /// This is where a developer can add the client specific information
    /// for creating a new customer.
    ///
    ///
    private CustomerRecord CreateCustomer()
    {
    CustomerRecord customer = new CustomerRecord();
    customer.CustomerId = String.Empty;

    customer.LastName = IPF.CRM.CustomerInformationSystem.Properties.Resources.DESKTOP_NEW_CUSTOMER + newCustomerNumber;
    customer.FirstName = IPF.CRM.CustomerInformationSystem.Properties.Resources.DESKTOP_NEW_CUSTOMER + newCustomerNumber;
    customer.Type = “contact”;
    newCustomerNumber++;

    return customer;
    }

    #endregion

    #region IDesktopUserActionsConsumer Members
    public void DesktopLoadingComplete()
    {
    }

    public void SetDesktopUserActionsAccess(IDesktopUserActions desktopAccess)
    {
    this.desktopAccess = desktopAccess;
    }
    #endregion

    #region Search Page
    ///
    /// Add a customer record found in a search to the listview control.
    ///
    ///
    private void fillList(CustomerRecord record)
    {
    if (record != null)
    collection.Add(record);
    }

    ///
    /// Look up a customer based on the customer ID.
    ///
    ///
    ///
    private void lookup_Click(object sender, EventArgs e)
    {
    try
    {
    Cursor = Cursors.Wait;

    errormsg.Content = string.Empty;
    results = null;
    collection.Clear();
    firstName.Text = firstName.Text.Trim();

    results = new CustomerRecord[10];

    results = oHelper.GetCustomer(firstName.Text, lastName1.Text, MobileNumber.Text, 10);
    //results = CustomerLookup.GetCustomer(firstName.Text, lastName.Text, phone.Text, id.Text, AccountName.Text, AccountNumber.Text,10);

    if (results != null)
    {
    foreach (CustomerRecord record in results)
    {
    fillList(record);
    }
    }
    if (resultsList.Items != null && resultsList.Items.Count > 0)
    {
    resultsList.SelectedIndex = 0;
    resultsList.Visibility = System.Windows.Visibility.Visible;
    resultsList.Focus();
    }
    else
    {
    errormsg.Content = IPF.CRM.CustomerInformationSystem.Properties.Resources.LOOKUP_DLG_UNABLE_CUST_ID; ;
    errormsg.Visibility = System.Windows.Visibility.Visible;
    }
    }
    catch (System.ServiceModel.FaultException)
    {
    }
    catch (System.Net.WebException wex) // v1.02
    {
    Logging.Error(productName, IPF.CRM.CustomerInformationSystem.Properties.Resources.DESKTOP_IIS_ERROR, wex);
    }
    catch (Exception exp)
    {
    Logging.Error(productName, IPF.CRM.CustomerInformationSystem.Properties.Resources.LOOKUP_DLG_UNABLE_CUST_RECORD, exp.Message);
    }
    finally
    {
    Cursor = Cursors.Arrow;
    }
    }

    ///
    /// Return to the caller the currently selected record.
    ///
    ///
    ///
    private void select_Click(object sender, EventArgs e)
    {
    errormsg.Content = “”;
    if (results != null && resultsList.SelectedItem != null)
    {
    Result = resultsList.SelectedItem as CustomerRecord;

    string MaxSessions = “5”;

    if (!string.IsNullOrEmpty(MaxSessions))
    {
    if (LocalSessionManager.Count < Convert.ToInt32(MaxSessions, CultureInfo.CurrentUICulture))
    //Search(Result);
    DoSearch(Result);
    else
    TopMostMessageBox.Show(IPF.CRM.CustomerInformationSystem.Properties.Resources.MAX_SESSION_COUNT_REACHED,
    IPF.CRM.CustomerInformationSystem.Properties.Resources.COMMON_MSGBOX_TITLE_PART2,
    System.Windows.Forms.MessageBoxButtons.OK);
    }
    else
    {
    DoSearch(Result);
    }
    }
    else
    {
    errormsg.Content = IPF.CRM.CustomerInformationSystem.Properties.Resources.LOOKUP_DLG_NO_RECORD_SELECTED;
    }
    }

    ///
    /// This is used by all the text entry controls to deselect any results when
    /// text is entered or deleted. This way a new search happens when enter is
    /// pressed.
    ///
    ///
    ///
    private void id_TextChanged(object sender, EventArgs e)
    {
    // deselect any results so a new search will happen if enter is pressed
    if (resultsList.SelectedIndex != -1)
    resultsList.SelectedIndex = -1;
    errormsg.Content = “”;
    }

    ///
    /// Returning OK with a null result indicates there is no customer match
    /// and an empty context needs to be created.
    ///
    ///
    ///
    private void btnNew_Click(object sender, RoutedEventArgs e)
    {
    Result = null;
    }

    private void lookupDlg_KeyUp(object sender, KeyEventArgs e)
    {
    if (e.Key.Equals(Key.Escape))
    {
    this.Close();
    }
    if (e.Key.Equals(Key.F) && (System.Windows.Forms.Control.ModifierKeys & System.Windows.Forms.Keys.Control) == System.Windows.Forms.Keys.Control)
    {
    if (!string.IsNullOrEmpty(Rfc.Text) ||
    !string.IsNullOrEmpty(MobileNumber.Text) ||
    !string.IsNullOrEmpty(lastName1.Text) ||
    !string.IsNullOrEmpty(firstName.Text) ||
    !string.IsNullOrEmpty(lastName2.Text) ||
    !string.IsNullOrEmpty(Address.Text) ||

    !string.IsNullOrEmpty(customerId.Text))
    {
    lookup_Click(this, null);
    }

    }
    if (e.Key.Equals(Key.Enter))
    {
    if (!resultsList.Items.Count.Equals(0))
    select_Click(this, null);
    }
    }
    #endregion

    [Obsolete(“The event is deprecated. The preferred way to start a session is to call the OpenSession method on IDesktopUserActions interface”, false)]
    public event EventHandler CustomerSearchResult;

    private void ButtonClear_Click(object sender, RoutedEventArgs e)
    {

    }
    }
    }

    Like

  10. Ram,

    I dont see you are assigning contact id while creating a customer record.

    private CustomerRecord CreateCustomer()
    {
    CustomerRecord customer = new CustomerRecord();
    customer.CustomerId = String.Empty;

    customer.LastName = IPF.CRM.CustomerInformationSystem.Properties.Resources.DESKTOP_NEW_CUSTOMER + newCustomerNumber;
    customer.FirstName = IPF.CRM.CustomerInformationSystem.Properties.Resources.DESKTOP_NEW_CUSTOMER + newCustomerNumber;
    customer.Type = “contact”;
    newCustomerNumber++;

    return customer;
    }

    If you are using this method, please assign id, So that we can use the same id while creating dyamiccustomerrecord. Please dont confuse. Customer record is different from dynamiccustomerrecord. We need to use dynamic customer record to open a session with id.

    Like

  11. Hi sreeni,

    sorry for that..

    private CustomerRecord CreateCustomer()
    {
    CustomerRecord customer = new CustomerRecord();
    customer.CustomerId = String.Empty;

    customer.LastName = IPF.CRM.CustomerInformationSystem.Properties.Resources.DESKTOP_NEW_CUSTOMER + newCustomerNumber;
    customer.FirstName = IPF.CRM.CustomerInformationSystem.Properties.Resources.DESKTOP_NEW_CUSTOMER + newCustomerNumber;
    customer.Type = “contact”;
    newCustomerNumber++;
    return customer;
    }
    can you please guide me what Id i have assign it here..

    Like

  12. Hi Sreeni,

    I want to capture the GUID of newly created contact record. I did as mentioned in Unified serviced Desk Help document. but it is not useful. Any Idea?

    USD COmponent type: CRM Page
    Event: Saved
    Occurs after a record in the CRM page is saved.
    newId – The ID assigned to the newly created record.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: