Response.Redirect Shim
March 14, 2026 · View on GitHub
The ResponseShim class provides compatibility with the ASP.NET Web Forms Response.Redirect() pattern. It wraps Blazor's NavigationManager so that migrated code-behind using Response.Redirect("~/Products.aspx") compiles and navigates correctly without rewriting.
Original Microsoft implementation: https://docs.microsoft.com/en-us/dotnet/api/system.web.httpresponse.redirect?view=netframework-4.8
Background
In ASP.NET Web Forms, server-side redirects were performed through the Response object:
// Web Forms code-behind
protected void btnSearch_Click(object sender, EventArgs e)
{
Response.Redirect("~/Products.aspx");
Response.Redirect("~/Products/Details.aspx?id=5", false);
Response.Redirect("~/Admin/Dashboard.aspx", true);
}
The Response object was available on every Page and UserControl via the inherited HttpResponse property.
Blazor Implementation
In Blazor, navigation is handled by NavigationManager.NavigateTo(). The ResponseShim bridges this gap by:
- Stripping
~/prefix — Converts~/pathto/path(virtual path resolution) - Stripping
.aspxextension — Converts/path.aspxto/path(Blazor uses extensionless routes) - Ignoring
endResponse— The second parameter has no meaning in Blazor's component model
Availability
ResponseShim is automatically available when your page inherits from WebFormsPageBase:
@inherits WebFormsPageBase
@code {
private void HandleClick()
{
// Works exactly like Web Forms
Response.Redirect("~/Products.aspx");
}
}
Web Forms Usage
// Common Web Forms patterns
Response.Redirect("~/Products.aspx");
Response.Redirect("~/Products/Details.aspx?id=" + productId);
Response.Redirect("~/Login.aspx", true); // endResponse = true
Response.Redirect("~/Dashboard.aspx", false); // endResponse = false
Blazor Usage
@inherits WebFormsPageBase
<Button Text="Go to Products" OnClick="GoToProducts" />
<Button Text="View Details" OnClick="ViewDetails" />
@code {
private int _selectedProductId = 5;
private void GoToProducts()
{
// ~/Products.aspx → /Products
Response.Redirect("~/Products.aspx");
}
private void ViewDetails()
{
// Query strings are preserved
Response.Redirect($"~/Products/Details.aspx?id={_selectedProductId}");
}
}
URL Transformations
| Web Forms URL | Blazor URL | Notes |
|---|---|---|
~/Products.aspx | /Products | ~/ stripped, .aspx removed |
~/Admin/Dashboard.aspx | /Admin/Dashboard | Path structure preserved |
~/Products.aspx?id=5 | /Products?id=5 | Query strings preserved |
/Products | /Products | Already-clean URLs pass through |
~/ | / | Root redirect |
Migration Path
The ResponseShim handles the most common redirect patterns. For each pattern:
| Web Forms Pattern | ResponseShim Support | Notes |
|---|---|---|
Response.Redirect(url) | ✅ Full | Primary use case |
Response.Redirect(url, endResponse) | ✅ Compiles | endResponse is ignored |
Response.RedirectPermanent(url) | ❌ Not supported | Use NavigationManager.NavigateTo() directly |
Response.Write(html) | ❌ Not supported | Not applicable in Blazor |
Response.StatusCode = 404 | ❌ Not supported | Use middleware or NavigationManager |
Moving On
Response.Redirect() is a migration bridge. As you refactor:
- Replace with
NavigationManager— InjectNavigationManagerand callNavigateTo()directly - Remove
.aspxfrom route references — Update string constants to use clean Blazor routes - Remove
~/prefixes — Use absolute paths (/Products) or relative navigation
@* Before (migration shim) *@
@inherits WebFormsPageBase
@code {
void Navigate() => Response.Redirect("~/Products.aspx");
}
@* After (native Blazor) *@
@inject NavigationManager Nav
@code {
void Navigate() => Nav.NavigateTo("/Products");
}
See Also
- WebFormsPage — Page-level base class providing the
Responseproperty - Page System — Title, MetaDescription, and other page-level services
- L2 Automation Shims — Overview of all migration automation features