title: How to generate new OrderHints when using Graph Api?
body: <p>I am trying to update <a href="https://docs.microsoft.com/en-us/graph/api/resources/plannerchecklistitem?view=graph-rest-1.0" rel="nofollow noreferrer">Planner Task details checklist items</a> using the <a href="https://docs.microsoft.com/en-us/graph/api/plannertaskdetails-update?view=graph-rest-1.0&amp;tabs=csharp" rel="nofollow noreferrer">GraphApi in C#</a>. The checklist entries have an order already from the source I am reading from (simple line numbers, <code>1..N</code>).</p>
  <p><a href="https://docs.microsoft.com/en-us/graph/api/resources/planner-order-hint-format?view=graph-rest-1.0" rel="nofollow noreferrer">Microsoft defines OrderHints like this</a>.</p>
  <p>If I set the order hints like this <code>0001, 0002, 0003 ...</code> and try to save the checklist I get an error saying <code>Specified order hint is in an invalid format: The input (0001) does not contain spaces or exclamation points.</code>. So I guess I can't use simple padded numbers (<code>$&quot;{lineNumber}&quot;.PadLeft(4, '0')</code>).</p>
  <p>I tried to put <code> !</code> at the end, like <code>0001 !, 0002 !, 0003 ! ...</code> and the api accepts the data that way, however the checklist entries are not in the order I meant to save them (just in a random order).</p>
  <p>How can I generate new <code>OrderHint</code>s for my entries?</p>
  <pre><code>private PlannerChecklistItems CheckListItemsFrom(SapPlannerSyncSalesOrder so)
  {
      var checklistItems = new PlannerChecklistItems();
      var soRows = so.Rows;
      if (soRows.Count == 0) return checklistItems;
  
      for (var i = 0; i &lt; soRows.Count; i++)
      {
          var row = soRows[i];
          //var orderHint = $&quot;{i+1}&quot;.PadLeft(6, '0');
  
          var orderHint = new string('A', i + 1);
  
          var newId = Guid.NewGuid().ToString(&quot;D&quot;);
  
          checklistItems[newId] = new PlannerChecklistItem
          {
              Title = row.AsPlannerCheckListTitle(),
              IsChecked = row.IsClosed(),
              OrderHint = $&quot;{orderHint}&quot;
          };
      }
  
      return checklistItems;
  }
  </code></pre>
  <p>Edit:
  I create the checklist items all at once. The plan this is for only uses the checklists to display sales order row statuses. So I just put the sale order rows in the checklist and mark them as checked if that part of the sales order is fulfilled (if the sales order row count &lt;= 20).</p>
  <p>If the sales order gets updated, I just re-create the checklist with new checklist items (delete the old ones by including them in the request, but setting their values to <code>null</code>). The checklist is not updated by hand, only the ERP can change a sales order.</p>
  <p>Because the sales order dictates the row order, I always have a simple, numerical order number I would like the checklists to have (<code>1,2,3...</code>).</p>
  <p>We use the planner browser client (<a href="https://tasks.office.com/" rel="nofollow noreferrer">https://tasks.office.com/</a>) and the &quot;random&quot; order gets saved like this, If I save my checklist items with order hints like <code> !</code> and <code> ! !</code>:</p>
  <pre><code>&quot;TaskDetails&quot;: {
      &quot;Checklist&quot;: {
        &quot;383f824c-b37d-4ab7-85a2-384bddfaf787&quot;: {
          &quot;Title&quot;: &quot;... - 1,00 db&quot;,
          &quot;OrderHint&quot;: &quot;}sb&quot;,
          &quot;IsChecked&quot;: false
        },
        &quot;7b0d9498-84d5-497f-9151-f0714bd78d82&quot;: {
          &quot;Title&quot;: &quot;.... - 1,00 db&quot;,
          &quot;OrderHint&quot;: &quot;yI&quot;,
          &quot;IsChecked&quot;: false
        },
        &quot;7c36d659-1265-490a-824f-9e78d800bfa7&quot;: {
          &quot;Title&quot;: &quot;....) - 3,00 óra&quot;,
          &quot;OrderHint&quot;: &quot;}PM&quot;,
          &quot;IsChecked&quot;: false
        },
        &quot;9530040d-4c2b-4840-a8cc-eb0be43a801a&quot;: {
          &quot;Title&quot;: &quot;...... - 1,00 db&quot;,
          &quot;OrderHint&quot;: &quot;lF&quot;,
          &quot;IsChecked&quot;: false
        },
        &quot;98ddf050-7c0b-45fd-8935-3faa1780c3d5&quot;: {
          &quot;Title&quot;: &quot;.... - 95,00 km&quot;,
          &quot;OrderHint&quot;: &quot;}gE&quot;,
          &quot;IsChecked&quot;: false
        },
        &quot;b593e4ce-4c5a-4af3-b7c2-e7e77a7bd6c4&quot;: {
          &quot;Title&quot;: &quot;.... - 1,00 db&quot;,
          &quot;OrderHint&quot;: &quot;|P&quot;,
          &quot;IsChecked&quot;: false
        },
        &quot;c6467ec2-ab2e-4e50-9025-56fb73ddbe32&quot;: {
          &quot;Title&quot;: &quot;.... - 1,00 db&quot;,
          &quot;OrderHint&quot;: &quot;}I&quot;,
          &quot;IsChecked&quot;: false
        },
        &quot;eec0c0b9-aece-4d8e-a8f8-33cc21946a91&quot;: {
          &quot;Title&quot;: &quot;..... - 4,50 l&quot;,
          &quot;OrderHint&quot;: &quot;uo&quot;,
          &quot;IsChecked&quot;: false
        },
        &quot;f108c8fe-4147-4146-adeb-cfbfab6c1151&quot;: {
          &quot;Title&quot;: &quot;.... - 1,00 db&quot;,
          &quot;OrderHint&quot;: &quot;{M&quot;,
          &quot;IsChecked&quot;: false
        },
        &quot;f2e31196-d15e-48d3-baaf-cefe739f7dd5&quot;: {
          &quot;Title&quot;: &quot;....- 1,00 db&quot;,
          &quot;OrderHint&quot;: &quot;[K&quot;,
          &quot;IsChecked&quot;: true
        }
  },
  </code></pre>
  <p>Update 2:</p>
  <p>The request to set the checklist looks like this (I manually converted the <code>PlannerTaskDetails</code> object to Json with <code>JsonConvert.SerializeObject()</code>):</p>
  <pre><code>{
    &quot;Checklist&quot;: [
      {
        &quot;Key&quot;: &quot;7287165c-06cb-47df-bfed-269922a5b357&quot;,
        &quot;Value&quot;: {
          &quot;IsChecked&quot;: false,
          &quot;LastModifiedBy&quot;: null,
          &quot;LastModifiedDateTime&quot;: null,
          &quot;OrderHint&quot;: &quot; !&quot;,
          &quot;Title&quot;: &quot;(.... - Ny: 99,00 db / Ö: 100,00 db&quot;,
          &quot;AdditionalData&quot;: null,
          &quot;ODataType&quot;: &quot;#microsoft.graph.plannerChecklistItem&quot;
        }
      },
      {
        &quot;Key&quot;: &quot;b5075d79-9f0a-4c1d-82aa-3f2fb40e1272&quot;,
        &quot;Value&quot;: {
          &quot;IsChecked&quot;: false,
          &quot;LastModifiedBy&quot;: null,
          &quot;LastModifiedDateTime&quot;: null,
          &quot;OrderHint&quot;: &quot; ! !&quot;,
          &quot;Title&quot;: &quot;(.... - 200,00 db&quot;,
          &quot;AdditionalData&quot;: null,
          &quot;ODataType&quot;: &quot;#microsoft.graph.plannerChecklistItem&quot;
        }
      },
      {
        &quot;Key&quot;: &quot;4c2c0faf-f720-490a-a929-e4f235d4cec9&quot;,
        &quot;Value&quot;: {
          &quot;IsChecked&quot;: false,
          &quot;LastModifiedBy&quot;: null,
          &quot;LastModifiedDateTime&quot;: null,
          &quot;OrderHint&quot;: &quot; ! ! !&quot;,
          &quot;Title&quot;: &quot;....- 300,00 db&quot;,
          &quot;AdditionalData&quot;: null,
          &quot;ODataType&quot;: &quot;#microsoft.graph.plannerChecklistItem&quot;
        }
      },
      {
        &quot;Key&quot;: &quot;9bffa151-f8fe-47fd-b52a-cae7b848266b&quot;,
        &quot;Value&quot;: {
          &quot;IsChecked&quot;: false,
          &quot;LastModifiedBy&quot;: null,
          &quot;LastModifiedDateTime&quot;: null,
          &quot;OrderHint&quot;: &quot; ! ! ! !&quot;,
          &quot;Title&quot;: &quot;... - 400,00 db&quot;,
          &quot;AdditionalData&quot;: null,
          &quot;ODataType&quot;: &quot;#microsoft.graph.plannerChecklistItem&quot;
        }
      }
    ],
    &quot;Description&quot;: &quot;...&quot;,
    &quot;PreviewType&quot;: 2,
    &quot;References&quot;: [],
    &quot;Id&quot;: &quot;4Gzvx5f3r0K0M....&quot;,
    &quot;ODataType&quot;: null,
    &quot;AdditionalData&quot;: {
      &quot;@odata.context&quot;: {
        &quot;ValueKind&quot;: 3
      },
      &quot;@odata.etag&quot;: {
        &quot;ValueKind&quot;: 3
      }
    }
  }
  </code></pre>
  <p>Calling code looks like this:</p>
  <pre><code>public async Task UpdatePlannerTaskDetails(
      string plannerTaskId, 
      string detailsEtag /* Details body has a different etag! */,
      PlannerTaskDetails taskDetails
  )
  {
      var client = await GetClient();
      await client
          .Planner
          .Tasks[plannerTaskId]
          .Details
          .Request()
          .Header(&quot;Prefer&quot;, &quot;return=representation&quot;)
          .Header(&quot;If-Match&quot;, detailsEtag)
          .UpdateAsync(taskDetails);
  }
  </code></pre>
  <p>Resulting details (captured the return of the UpdateAsync):</p>
  <pre><code>{
    &quot;Checklist&quot;: [
      {
        &quot;Key&quot;: &quot;0bd81e93-b4cb-4426-812a-400a7e829166&quot;,
        &quot;Value&quot;: {
          &quot;IsChecked&quot;: false,
          &quot;LastModifiedBy&quot;: {
            &quot;Application&quot;: null,
            &quot;Device&quot;: null,
            &quot;User&quot;: {
              &quot;DisplayName&quot;: null,
              &quot;Id&quot;: &quot;c21b0185-....&quot;,
              &quot;AdditionalData&quot;: null,
              &quot;ODataType&quot;: null
            },
            &quot;AdditionalData&quot;: null,
            &quot;ODataType&quot;: null
          },
          &quot;LastModifiedDateTime&quot;: &quot;2022-06-28T08:26:42.8180847+02:00&quot;,
          &quot;OrderHint&quot;: &quot;[i&quot;,
          &quot;Title&quot;: &quot;.... - 200,00 db&quot;,
          &quot;AdditionalData&quot;: null,
          &quot;ODataType&quot;: &quot;#microsoft.graph.plannerChecklistItem&quot;
        }
      },
      {
        &quot;Key&quot;: &quot;0071647c-bd62-4102-8278-2a837ff1ec26&quot;,
        &quot;Value&quot;: {
          &quot;IsChecked&quot;: false,
          &quot;LastModifiedBy&quot;: {
            &quot;Application&quot;: null,
            &quot;Device&quot;: null,
            &quot;User&quot;: {
              &quot;DisplayName&quot;: null,
              &quot;Id&quot;: &quot;c21b0185-....&quot;,
              &quot;AdditionalData&quot;: null,
              &quot;ODataType&quot;: null
            },
            &quot;AdditionalData&quot;: null,
            &quot;ODataType&quot;: null
          },
          &quot;LastModifiedDateTime&quot;: &quot;2022-06-28T08:26:42.8180847+02:00&quot;,
          &quot;OrderHint&quot;: &quot;8585452093426908086PY&quot;,
          &quot;Title&quot;: &quot;.... - Ny: 99,00 db / Ö: 100,00 db&quot;,
          &quot;AdditionalData&quot;: null,
          &quot;ODataType&quot;: &quot;#microsoft.graph.plannerChecklistItem&quot;
        }
      },
      {
        &quot;Key&quot;: &quot;ad5572ca-ad2a-4e69-bf4c-24e039ca0cd9&quot;,
        &quot;Value&quot;: {
          &quot;IsChecked&quot;: false,
          &quot;LastModifiedBy&quot;: {
            &quot;Application&quot;: null,
            &quot;Device&quot;: null,
            &quot;User&quot;: {
              &quot;DisplayName&quot;: null,
              &quot;Id&quot;: &quot;c21b0185-....&quot;,
              &quot;AdditionalData&quot;: null,
              &quot;ODataType&quot;: null
            },
            &quot;AdditionalData&quot;: null,
            &quot;ODataType&quot;: null
          },
          &quot;LastModifiedDateTime&quot;: &quot;2022-06-28T08:26:42.8180847+02:00&quot;,
          &quot;OrderHint&quot;: &quot;l^&quot;,
          &quot;Title&quot;: &quot;.... - 300,00 db&quot;,
          &quot;AdditionalData&quot;: null,
          &quot;ODataType&quot;: &quot;#microsoft.graph.plannerChecklistItem&quot;
        }
      },
      {
        &quot;Key&quot;: &quot;c29e44cd-8404-4b65-bb5b-10cf1bda345c&quot;,
        &quot;Value&quot;: {
          &quot;IsChecked&quot;: false,
          &quot;LastModifiedBy&quot;: {
            &quot;Application&quot;: null,
            &quot;Device&quot;: null,
            &quot;User&quot;: {
              &quot;DisplayName&quot;: null,
              &quot;Id&quot;: &quot;c21b0185-....&quot;,
              &quot;AdditionalData&quot;: null,
              &quot;ODataType&quot;: null
            },
            &quot;AdditionalData&quot;: null,
            &quot;ODataType&quot;: null
          },
          &quot;LastModifiedDateTime&quot;: &quot;2022-06-28T08:26:42.8180847+02:00&quot;,
          &quot;OrderHint&quot;: &quot;uy&quot;,
          &quot;Title&quot;: &quot;.... - 400,00 db&quot;,
          &quot;AdditionalData&quot;: null,
          &quot;ODataType&quot;: &quot;#microsoft.graph.plannerChecklistItem&quot;
        }
      }
    ],
    &quot;Description&quot;: &quot;....&quot;,
    &quot;PreviewType&quot;: 2,
    &quot;References&quot;: [],
    &quot;Id&quot;: &quot;4Gzvx5f3r0K0Mx41...&quot;,
    &quot;ODataType&quot;: null,
    &quot;AdditionalData&quot;: {
      &quot;@odata.context&quot;: {
        &quot;ValueKind&quot;: 3
      },
      &quot;@odata.etag&quot;: {
        &quot;ValueKind&quot;: 3
      }
    }
  }
  </code></pre>
  <p>Somehow even the keys get changed after update.</p>
  <p>The order displayed in planner:
  <a href="https://i.stack.imgur.com/Nploc.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Nploc.png" alt="enter image description here" /></a></p>
  <p>Usually, the order is just random, not reversed.</p>
  <p>If I manually complete a checklist item and capture the request in the browser console, the checklist:</p>
  <pre><code>&quot;TaskDetails&quot;: {
  &quot;Checklist&quot;: {
    &quot;0071647c-bd62-4102-8278-2a837ff1ec26&quot;: {
      &quot;Title&quot;: &quot;.... - Ny: 99,00 db / Ö: 100,00 db&quot;,
      &quot;OrderHint&quot;: &quot;8585452093426908086PY&quot;,
      &quot;IsChecked&quot;: true
    },
    &quot;0bd81e93-b4cb-4426-812a-400a7e829166&quot;: {
      &quot;Title&quot;: &quot;.... - 200,00 db&quot;,
      &quot;OrderHint&quot;: &quot;[i&quot;,
      &quot;IsChecked&quot;: false
    },
    &quot;ad5572ca-ad2a-4e69-bf4c-24e039ca0cd9&quot;: {
      &quot;Title&quot;: &quot;... - 300,00 db&quot;,
      &quot;OrderHint&quot;: &quot;l^&quot;,
      &quot;IsChecked&quot;: false
    },
    &quot;c29e44cd-8404-4b65-bb5b-10cf1bda345c&quot;: {
      &quot;Title&quot;: &quot;.... - 400,00 db&quot;,
      &quot;OrderHint&quot;: &quot;uy&quot;,
      &quot;IsChecked&quot;: false
    }
  },
  &quot;CompletedBy&quot;: null,
  &quot;Description&quot;: &quot;...&quot;,
  &quot;PreviewType&quot;: 2,
  &quot;References&quot;: {},
  &quot;Id&quot;: &quot;4Gzvx5f3r0K0Mx....&quot;,
  &quot;ItemVersion&quot;: 6,
  &quot;Type&quot;: 2
  },
  </code></pre>