How to add an 'operations' link to a custom route? I'm implementing a custom entity with bundles in Drupal 8.

In the list of bundle entities page (i.e. equivalent to Node's Content Types listing page), I would like to provide an extra option to the list of operations, which currently include Edit, Manage Fields, Manage Display, Delete, to let the user create an entity of that bundle. So if this were on Nodes, then it would be like adding an "Add Content" link for each content type in the content listing page, which would take you to /node/add/{node_type}.

Relevant code I have so far:

Added an 'add-entity' option in the links section of the config entity's annotations:

* @ConfigEntityType(
*   id = "bloom_stem_type",
*   label = @Translation("BloomStemType"),
*   bundle_of = "bloom_stem",
*   ...
*   links = {
*     "edit-form" = "entity.bloom_stem_type.edit_form",
*     "delete-form" = "entity.bloom_stem_type.delete_form",
*     "collection" = "entity.bloom_stem_type.collection",
*     "add-entity" = "entity.bloom_stem.add_form"
*   }
* )
*/


Note that this points to a route in another entity, the actual entity that this is a bundle for.

That route is defined in (routing.yml):

entity.bloom_stem.add_form:
  path: '/admin/bloom_stem/{bloom_stem_type}/add'
  defaults:
    _title: 'Add BloomStem'
    _controller: '\Drupal\bloom\Controller\BloomStemController::addForm'
  requirements:
    _entity_create_access: 'bloom_stem'


Then I've implemented getDefaultOperations on a custom list builder class:

class BloomStemTypeListBuilder extends ConfigEntityListBuilder {
  ...
  /**
   * Gets this list's default operations.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity the operations are for.
   *
   * @return array
   *   The array structure is identical to the return value of
   *   self::getOperations().
   */
  public function getDefaultOperations(EntityInterface $entity) {
    $operations = parent::getDefaultOperations($entity);

    $operations['add'] = array(
      'title' =&gt; $this-&gt;t('Add'),
      'weight' =&gt; 10,
      'url' =&gt; $entity-&gt;urlInfo('add-entity'),
    );

    return $operations;
  }


However, when I visit the entity bundles list page, there's an exception thrown about being unable to create a route/path. On step-through debugging this seems to be because Entity::urlInfo() does not appear to use the route set in the annotation, thanks to this line that constructs its own route:

$route_name = "entity.{$this-&gt;entityTypeId}." . str_replace(array('-', 'drupal:'), array('_', ''), $rel);


The only documentation I could find on the links part of the annotation just
says:


  links
  Entity URL definitions, referencing to routes from MODULE.routing.yml.
  'canonical' is the default route for the entity. edit-form and delete-form
  can also be set. These are mostly used for Field UI. Arbitrary keys can set
  here. For example, User sets cancel-form, while Node uses delete-form.


Which I took to mean ("referencing to routes from MODULE.routing.yml") that if I
referenced a route, that route would be used.

Aside: Other things I've tried include creating the URL more directly (clearly not the
right way of doing things):

$url = \Drupal::getContainer()-&gt;get('url_generator')
  -&gt;generateFromRoute('entity.bloom_stem.add_form', ['bloom_stem_type'=&gt;$entity-&gt;id()]);


That generates a valid path, but a string value is not what getOperations
is expected to spit out under its url key output.

Can anyone fill me in on how this is supposed to work/where I've gone wrong?
Thanks.
What drupal core version are you using?

Link templates have been changed to links instead of route names a few months ago. See Node and other example entity types.

Another requirement is that link template names and route names need to match.

However, your primary problem is that link templates about the entity or at least entity type that you have, and that's not the case for your example.

Using link templates for operations is convenient when possible but in no way required. It can be any Url object. So your last attempt is actually close, you're just not using the right API yet (and yes, there are definitely way too many ways to generate links/URL's).

Try this:

\Drupal\Core\Url::fromRoute('entity.bloom_stem.add_form', ['bloom_stem_type' =&gt; $entity-&gt;id()])


Then use that for 'url'.