title: Blazor: Redirecting request with query string data
body: <p>I'm working on a new website based in Blazor, coming from a largely MVC background.  I have a page, that page has a singular object ID, and based on that ID, the page can display an arbitrary number of records.  The routing is defined with a simple singular parameter.</p>
  <p><code>@page &quot;/MyPage/{ObjectID:int}&quot;</code></p>
  <p>While this is fine for most cases, I also have a feature request for users to be able to directly navigate to a particular record on this page.  I thought this would be easiest to accomplish with a query string.  So an example URL would look like this.</p>
  <p><code>/MyPage/12345?recordID=ABCDE</code></p>
  <p>Now here's the kicker.  For SEO purposes, I don't want the query string to remain in the URL.  Since I don't want variations of the page with different query strings appearing on Google, I want to accomplish this with a Redirect status code.  [Note: I'm not all that knowledgeable on SEO, but this came directly from the client, so I'm more or less stuck with the requirement]  So I want to take that <code>ABCDEF</code> value from <code>recordID</code>, store it off somewhere, and then redirect to the base URL without the query string, where it can then find that <code>ABCDEF</code> value and render the page directly to that record.  And that's where I'm struggling.</p>
  <p>Given how Blazor handles state and rendering changes, I kinda thought the architecture would be perfect for this scenario.  However, NavigationManager does not appear to be anywhere near as extensive as the ActionResults I'm used to.  My basic idea was to record the record ID, <code>NavigateTo</code> the base URL with <code>forceLoad</code> false and <code>replace</code> true parameters, and utilize the LocationChanged event to capture the event and prevent the actual browser navigation.  Here's what I've tried.</p>
  <p><strong>In OnInitializedAsync</strong></p>
  <ul>
  <li>Good: 302 redirects to the base page without the query string.</li>
  <li>Bad: LocationChanged event does not fire. According to <a href="https://chrissainty.com/an-in-depth-look-at-routing-in-blazor/" rel="nofollow noreferrer">this article</a>, this is because navigation interruption is not enabled until OnAfterRender.</li>
  <li>Bad: The browser redirects to the base page, but the recorded record ID is not saved.</li>
  </ul>
  <p><strong>In OnAfterRenderAsync</strong></p>
  <ul>
  <li>Good: LocationChanged fires and intercepts the browser navigation.</li>
  <li>Good: The browser URL updates, and the page renders to the expected record.</li>
  <li>Bad: The request with the query string returns a 200 response code. No evidence of the request for the base URL without the query string can be found.</li>
  </ul>
  <p><strong>Cookies, maybe?</strong></p>
  <ul>
  <li>Thought Process: Based on what I've learned from the previous attempts, maybe I can read the query string value, record it as a cookie, and navigate to the base URL in OnInitializedAsync, then read and delete that cookie in OnInitializedAsync at the base URL.</li>
  <li>Bad: As far as I can tell, Blazor web assembly doesn't have any sort of cookie management tools, because it expects you to use JS interop.  But JS interop isn't available  until OnAfterRender.</li>
  </ul>
  <p>And from there, I'm out of ideas.  I was hoping to be able to utilize something like <code>RedirectPreserveMethod</code> to accomplish this, but Blazor really doesn't seem to want you to have any control over the Request/Response experience that I'm used to.  Is there anything I can do to get the best of both worlds here, with a redirect status response and persisting the record ID? Or am I stuck with the options I've already tried?</p>