diff --git a/CRM/Contribute/Form/CancelSubscription.php b/CRM/Contribute/Form/CancelSubscription.php
index 27d7f4de416cacbdab5b27d7c1725a09233c16d0..bd84cdca3c953acbb1dbbb485f2d6ab416809be7 100644
--- a/CRM/Contribute/Form/CancelSubscription.php
+++ b/CRM/Contribute/Form/CancelSubscription.php
@@ -40,7 +40,25 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
 
   protected $_mode = NULL;
 
-  protected $_selfService = FALSE;
+  /**
+   * Should custom data be suppressed on this form.
+   *
+   * We override to suppress custom data because historically it has not been
+   * shown on this form & we don't want to expose it as a by-product of
+   * other change without establishing that it would be good on this form.
+   *
+   * @return bool
+   */
+  protected function isSuppressCustomData() {
+    return TRUE;
+  }
+
+  /**
+   * Is the from being accessed by a front end user to update their own recurring.
+   *
+   * @var bool
+   */
+  protected $selfService;
 
   /**
    * Set variables up before form is built.
@@ -91,33 +109,49 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
       (!$this->_crid && !$this->_coid && !$this->_mid) ||
       (!$this->_subscriptionDetails)
     ) {
-      CRM_Core_Error::fatal('Required information missing.');
+      CRM_Core_Error::statusBounce('Required information missing.');
     }
 
-    if (!CRM_Core_Permission::check('edit contributions')) {
-      if ($this->_subscriptionDetails->contact_id != $this->getContactID()) {
-        CRM_Core_Error::statusBounce(ts('You do not have permission to cancel this recurring contribution.'));
-      }
-      $this->_selfService = TRUE;
-    }
-    $this->assign('self_service', $this->_selfService);
-
     // handle context redirection
     CRM_Contribute_BAO_ContributionRecur::setSubscriptionContext();
 
     CRM_Utils_System::setTitle($this->_mid ? ts('Cancel Auto-renewal') : ts('Cancel Recurring Contribution'));
     $this->assign('mode', $this->_mode);
 
+    if ($this->isSelfService()) {
+      unset($this->entityFields['send_cancel_request'], $this->entityFields['is_notify']);
+    }
+
     if ($this->_subscriptionDetails->contact_id) {
       list($this->_donorDisplayName, $this->_donorEmail)
         = CRM_Contact_BAO_Contact::getContactDetails($this->_subscriptionDetails->contact_id);
     }
   }
 
+  /**
+   * Set entity fields for this cancellation.
+   */
+  public function setEntityFields() {
+    $this->entityFields = [
+      'cancel_reason' => ['name' => 'cancel_reason'],
+    ];
+    $this->entityFields['send_cancel_request'] = [
+      'title' => ts('Send cancellation request to %1 ?', [1 => $this->_paymentProcessorObj->_processorName]),
+      'name' => 'send_cancel_request',
+      'not-auto-addable' => TRUE,
+    ];
+    $this->entityFields['is_notify'] = [
+      'title' => ts('Notify Contributor?'),
+      'name' => 'is_notify',
+      'not-auto-addable' => TRUE,
+    ];
+  }
+
   /**
    * Build the form object.
    */
   public function buildQuickForm() {
+    $this->buildQuickEntityForm();
     // Determine if we can cancel recurring contribution via API with this processor
     $cancelSupported = $this->_paymentProcessorObj->supports('CancelRecurring');
     if ($cancelSupported) {
@@ -145,7 +179,7 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
     }
 
     $type = 'next';
-    if ($this->_selfService) {
+    if ($this->isSelfService()) {
       $type = 'submit';
     }
 
@@ -184,7 +218,7 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
     $cancelSubscription = TRUE;
     $params = $this->controller->exportValues($this->_name);
 
-    if ($this->_selfService) {
+    if ($this->isSelfService()) {
       // for self service force sending-request & notify
       if ($this->_paymentProcessorObj->supports('cancelRecurring')) {
         $params['send_cancel_request'] = 1;
@@ -209,6 +243,7 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
           'id' => $this->_subscriptionDetails->recur_id,
           'membership_id' => $this->_mid,
           'processor_message' => $message,
+          'cancel_reason' => $params['cancel_reason'],
         ]);
 
         $tplParams = [];
@@ -308,4 +343,23 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
     }
   }
 
+  /**
+   * Is this being used by a front end user to update their own recurring.
+   *
+   * @return bool
+   */
+  protected function isSelfService() {
+    if (!is_null($this->selfService)) {
+      return $this->selfService;
+    }
+    $this->selfService = FALSE;
+    if (!CRM_Core_Permission::check('edit contributions')) {
+      if ($this->_subscriptionDetails->contact_id != $this->getContactID()) {
+        CRM_Core_Error::statusBounce(ts('You do not have permission to cancel this recurring contribution.'));
+      }
+      $this->selfService = TRUE;
+    }
+    return $this->selfService;
+  }
+
 }
diff --git a/CRM/Contribute/Form/ContributionRecur.php b/CRM/Contribute/Form/ContributionRecur.php
index 24ad75822273808065cae65e4001a053d9d3aea3..602cbe9d2fee8e8ce5c83421e59fc4dba8074750 100644
--- a/CRM/Contribute/Form/ContributionRecur.php
+++ b/CRM/Contribute/Form/ContributionRecur.php
@@ -107,6 +107,15 @@ class CRM_Contribute_Form_ContributionRecur extends CRM_Core_Form {
     return 'create';
   }
 
+  /**
+   * Get the entity id being edited.
+   *
+   * @return int|null
+   */
+  public function getEntityId() {
+    return $this->contributionRecurID;
+  }
+
   /**
    * Set variables up before form is built.
    */
diff --git a/CRM/Core/Form/EntityFormTrait.php b/CRM/Core/Form/EntityFormTrait.php
index 00a5c5b6e0922e7143081f1163669e29914d59aa..ff4c41c9403cb1efba827c1533ddc0fd50f52b1b 100644
--- a/CRM/Core/Form/EntityFormTrait.php
+++ b/CRM/Core/Form/EntityFormTrait.php
@@ -87,6 +87,15 @@ trait CRM_Core_Form_EntityFormTrait {
     return $this->_id;
   }
 
+  /**
+   * Should custom data be suppressed on this form.
+   *
+   * @return bool
+   */
+  protected function isSuppressCustomData() {
+    return FALSE;
+  }
+
   /**
    * Get the entity subtype ID being edited
    *
@@ -105,6 +114,9 @@ trait CRM_Core_Form_EntityFormTrait {
    * If the custom data is in the submitted data (eg. added via ajax loaded form) add to form.
    */
   public function addCustomDataToForm() {
+    if ($this->isSuppressCustomData()) {
+      return TRUE;
+    }
     $customisableEntities = CRM_Core_SelectValues::customGroupExtends();
     if (isset($customisableEntities[$this->getDefaultEntity()])) {
       CRM_Custom_Form_CustomData::addToForm($this);
diff --git a/templates/CRM/Contribute/Form/CancelSubscription.tpl b/templates/CRM/Contribute/Form/CancelSubscription.tpl
index 3d1d3dba58ece6cc889b5c66c96fd691cd495ff2..ed8395b652bf7e1a16a13095fe353ec962c22eba 100644
--- a/templates/CRM/Contribute/Form/CancelSubscription.tpl
+++ b/templates/CRM/Contribute/Form/CancelSubscription.tpl
@@ -42,17 +42,5 @@
     </div>
   {/if}
 </div>
-{if !$self_service}
-<table class="form-layout">
-   <tr>
-      <td class="label">{$form.send_cancel_request.label}</td>
-      <td class="html-adjust">{$form.send_cancel_request.html}</td>
-   </tr>
-   <tr>
-      <td class="label">{$form.is_notify.label}</td>
-      <td class="html-adjust">{$form.is_notify.html}</td>
-   </tr>
-</table>
-{/if}
-<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="top"}</div>
+  {include file="CRM/Core/Form/EntityForm.tpl"}
 </div>
diff --git a/templates/CRM/Contribute/Page/ContributionRecur.tpl b/templates/CRM/Contribute/Page/ContributionRecur.tpl
index 36c86d4f79888521cea3bf02f6d339c6fcfdedc3..525705ded5c1409f68a8069edf1e380bc07fe5a7 100644
--- a/templates/CRM/Contribute/Page/ContributionRecur.tpl
+++ b/templates/CRM/Contribute/Page/ContributionRecur.tpl
@@ -47,6 +47,7 @@
             <tr><td class="label">{ts}Created Date{/ts}</td><td>{$recur.create_date|crmDate}</td></tr>
             {if $recur.modified_date}<tr><td class="label">{ts}Modified Date{/ts}</td><td>{$recur.modified_date|crmDate}</td></tr>{/if}
             {if $recur.cancel_date}<tr><td class="label">{ts}Cancelled Date{/ts}</td><td>{$recur.cancel_date|crmDate}</td></tr>{/if}
+            {if $recur.cancel_reason}<tr><td class="label">{ts}Cancel Reason{/ts}</td><td>{$recur.cancel_reason}</td></tr>{/if}
             {if $recur.end_date}<tr><td class="label">{ts}End Date{/ts}</td><td>{$recur.end_date|crmDate}</td></tr>{/if}
             {if $recur.processor_id}<tr><td class="label">{ts}Processor ID{/ts}</td><td>{$recur.processor_id}</td></tr>{/if}
             <tr><td class="label">{ts}Transaction ID{/ts}</td><td>{$recur.trxn_id}</td></tr>