SwapView - Intelligent Request Handling

Auto-detect HTMX requests and return partials or full pages automatically.

Overview

SwapView is the foundation of Swap.Htmx. It automatically detects whether a request comes from HTMX or a regular browser, returning just the partial for HTMX requests and the full page with layout for direct navigation.

Write your view once. It works everywhere.


Basic Usage

public class ProductsController : SwapController
{
    public IActionResult Index()
    {
        var products = _productService.GetAll();
        return SwapView(products);  // Returns Index.cshtml
    }
}

How It Works

  • HTMX request (HX-Request header present): Returns only the view content
  • Browser navigation (direct URL access): Returns view wrapped in layout
  • Bookmarkable: Every HTMX-loaded URL can be accessed directly

Specifying View Names

// Use a specific view name
public IActionResult Details(int id)
{
    var product = _productService.GetById(id);
    return SwapView("ProductDetails", product);
}

// Use a partial view
public IActionResult ProductList()
{
    var products = _productService.GetAll();
    return SwapView("_ProductList", products);
}

Benefits

1. No Duplicate Views

Traditional approach requires separate views for partials and full pages:

Views/
  Products/
    Index.cshtml        # Full page
    _IndexPartial.cshtml  # HTMX partial (duplicate!)

With SwapView, you only need one:

Views/
  Products/
    Index.cshtml        # Works for both!

2. Progressive Enhancement

Users can bookmark and share any URL, even if it was originally loaded via HTMX:

https://myapp.com/products/42

Works whether accessed directly or through HTMX navigation.

3. Simplified Testing

Test one view for both scenarios instead of maintaining two separate views.


Advanced: Custom Layout Behavior

Control layout suppression per-request:

public IActionResult Special()
{
    // Force no layout even for browser requests
    ViewData["SuppressLayout"] = true;
    return SwapView();
}

Or in _ViewStart.cshtml:

@using Swap.Htmx
@{
    Layout = Context.ShouldSuppressLayout() ? null : "_Layout";
}

Tips

  • Use meaningful view names: SwapView("_ProductCard", product) is clearer than SwapView("_PC", product)
  • Leverage Source Generators: Use SwapViews.Products.Index instead of magic strings
  • Keep partials focused: One responsibility per partial makes them easier to reuse