EndpointHelpers by Gustavo Mauricio de Barros
NuGet / site data
Details
Info
Name: EndpointHelpers
Source generators that add strongly-typed UrlHelper and LinkGenerator APIs for ASP.NET Core MVC controllers.
Author: Gustavo Mauricio de Barros
NuGet: https://www.nuget.org/packages/EndpointHelpers/
You can find more details at https://github.com/gumbarros/EndpointHelpers
Author
Gustavo Mauricio de Barros

Original Readme
EndpointHelpers
EndpointHelpers is a Roslyn source generator that creates strongly-typed helpers for ASP.NET Core MVC controllers. It generates:
IUrlHelperhelpers with action methods per controller.LinkGeneratorhelpers withGet{Action}Pathmethods, includingHttpContextoverloads.- Redirect helpers for controller actions, so
RedirectToAction("Index")becomesRedirectToIndex(). - View helpers on controllers, so
return View("Index")becomesreturn IndexView(). - Extension properties on
IUrlHelperandLinkGeneratorto access the helpers. - Attribute types are used to control generation.
This package ships only a source generator and generated code. There is no runtime dependency.
Example
######### Without the generator
<a href='@Url.Action(action: "Details",controller: "Orders", values: new \{ orderId = 123, source = "dashboard" \} )'>
View order
</a>
######### With the generator enabled
<a href='@Url.Orders.Details(123, "dashboard")'>
View order
</a>
Install
Add the NuGet package:
<ItemGroup>
<PackageReference Include="EndpointHelpers" Version="2.0.2"/>
</ItemGroup>
or
dotnet add package EndpointHelpers
Requirements
The generated code uses C# 14 extension members (extension(...) blocks), so consumers must compile with a C# 14 toolchain (the .NET 10 SDK or later).
Optional (for better IntelliSense in JetBrains IDEs):
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2025.2.4" />
</ItemGroup>
When JetBrains.Annotations is installed, generated MVC helper methods include ASP MVC annotations, and IntelliSense/navigation for views and model parameters works correctly when using R### or Rider.
Quick Start
Enable generation at the assembly level:
using EndpointHelpers;
[assembly: GenerateUrlHelper]
[assembly: GenerateLinkGenerator]
Or apply to a specific controller:
using EndpointHelpers;
[GenerateUrlHelper]
[GenerateLinkGenerator]
[GenerateRedirectToAction]
[GenerateViewHelpers]
public partial class HomeController : Controller
{
public IActionResult Index() => View();
public IActionResult Privacy() => View();
}
Or only to a specific action:
using EndpointHelpers;
public partial class HomeController : Controller
{
[GenerateUrlHelper]
[GenerateRedirectToAction]
public IActionResult Index() => View();
public IActionResult Privacy() => View();
}
Redirect example:
public partial class OrdersController : Controller
{
public IActionResult Index() => View();
[GenerateRedirectToAction]
public IActionResult Details(int orderId, string? source) => View();
public IActionResult Save()
{
return RedirectToDetails(orderId: 123, source: "created");
}
}
Attributes and Scope
Generation can be enabled at different scopes:
- Assembly:
[assembly: GenerateUrlHelper],[assembly: GenerateLinkGenerator]. - Controller:
[GenerateUrlHelper],[GenerateLinkGenerator],[GenerateRedirectToAction]on the controller class. - Action:
[GenerateUrlHelper],[GenerateLinkGenerator],[GenerateRedirectToAction]on a specific action method. - View helpers:
[GenerateViewHelpers]on the controller class (controller-only, not per-action or assembly). GenerateRedirectToActiondoes not support assembly-level attributes and requires controllers declaredpartial.GenerateViewHelpersdoes not support assembly-level attributes and requires controllers declaredpartial.
You can exclude methods using:
[UrlHelperIgnore][LinkGeneratorIgnore][RedirectToActionIgnore][NonAction](standard ASP.NET Core MVC attribute)
Behavior
- Controllers are discovered by name: non-abstract classes ending with
Controller. - Only public, ordinary methods are included.
- UrlHelper and LinkGenerator helpers are placed in the
EndpointHelpersnamespace. - Redirect helpers are generated as
partialmembers in the controller namespace. - Extension properties use the controller name without the
Controllersuffix. - Controllers with
[Area("...")]are grouped by area, so generated access becomesUrl.<Area>.<Controller>andLinks.<Area>.<Controller>. - Only route-value-compatible parameters are included: simple types (
int,string,Guid,DateTime, enums, nullables, ...) or parameters marked[FromRoute]/[FromQuery]/[FromHeader]/[FromForm]. Body-bound parameters (complex types or[FromBody]) are excluded, andCancellationToken/[FromServices]parameters are always ignored.
######### Controller and action discovery
[GenerateUrlHelper]
[GenerateLinkGenerator]
[GenerateRedirectToAction]
public partial class OrdersController : Controller
{
public IActionResult Index() => View();
public IActionResult Details(int orderId, string? source) => View();
}
######### Optional Optimization
Caching controller helpers avoid repeated allocations. This is a micro-optimization and usually not necessary in most scenarios. It can make sense in hot views where you call the same helper many times (for example, in a loop), but the savings are typically negligible compared to database access, rendering, or network costs. If you don’t measure a problem, skip this.
@{
var ordersUrlHelper = Url.Orders;
}
@for (var i = 0; i < Model.Orders.Count; i++)
{
var order = Model.Orders[i];
<a class="btn btn-sm btn-outline-secondary" href="@ordersUrlHelper.Details(order.Id)">Details</a>
}
########## Generated surface
// UrlHelperGenerator
Url.Orders.Index();
Url.Orders.Details(orderId: 123, source: "dashboard");
Url.Admin.Users.Index();
// LinkGeneratorGenerator
LinkGenerator.Orders.GetIndexPath();
LinkGenerator.Orders.GetDetailsPath(123, "dashboard");
LinkGenerator.Admin.Users.GetIndexPath();
// RedirectToActionGenerator
RedirectToIndex();
RedirectToDetails(orderId: 123, source: "dashboard");
RedirectToUsers();
Example Project
See example/EndpointHelpers.Sample for a minimal MVC app using all generators.
License
GNU General Public License
About
Generating endpoint helpers for ASP.NET Core MVC
How to use
Example (source csproj, source files)
- CSharp Project
- Program.cs
- HomeController.cs
- Privacy.cshtml
This is the CSharp Project that references EndpointHelpers
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="EndpointHelpers" Version="2.0.2" />
</ItemGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
</Project>
This is the use of EndpointHelpers in Program.cs
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
//app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.MapStaticAssets();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
.WithStaticAssets();
app.Run();
This is the use of EndpointHelpers in HomeController.cs
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using TestMVC.Models;
using EndpointHelpers;
namespace TestMVC.Controllers;
[GenerateUrlHelper]
[GenerateLinkGenerator]
[GenerateRedirectToAction]
[GenerateViewHelpers]
public partial class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel \{ RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
This is the use of EndpointHelpers in Privacy.cshtml
@using EndpointHelpers;
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
<a href="@Url.Home.Index()"> This is the index referenced directly</a>
Generated Files
Those are taken from $(BaseIntermediateOutputPath)\GX
- LinkGeneratorExtensions.g.cs
- RedirectToActionControllers.g.cs
- Attributes.g.cs
- Microsoft.CodeAnalysis.EmbeddedAttribute.cs
- UrlHelperExtensions.g.cs
- ViewHelpers.g.cs
// <auto-generated/>
#nullable enable
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
namespace EndpointHelpers;
public sealed class HomeControllerLinkGenerator(LinkGenerator linkGenerator)
{
public string GetIndexPath()
{
return linkGenerator.GetPathByAction(
action: "Index",
controller: "Home",
values: null)!;
}
public string GetIndexPath(HttpContext httpContext)
{
return linkGenerator.GetPathByAction(
httpContext,
action: "Index",
controller: "Home",
values: null)!;
}
public string GetPrivacyPath()
{
return linkGenerator.GetPathByAction(
action: "Privacy",
controller: "Home",
values: null)!;
}
public string GetPrivacyPath(HttpContext httpContext)
{
return linkGenerator.GetPathByAction(
httpContext,
action: "Privacy",
controller: "Home",
values: null)!;
}
public string GetErrorPath()
{
return linkGenerator.GetPathByAction(
action: "Error",
controller: "Home",
values: null)!;
}
public string GetErrorPath(HttpContext httpContext)
{
return linkGenerator.GetPathByAction(
httpContext,
action: "Error",
controller: "Home",
values: null)!;
}
}
public static class LinkGeneratorExtensions
{
extension(LinkGenerator linkGenerator)
{
public HomeControllerLinkGenerator Home => new HomeControllerLinkGenerator(linkGenerator);
}
}
// <auto-generated/>
#nullable enable
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
namespace TestMVC.Controllers
{
public partial class HomeController
{
protected RedirectToActionResult RedirectToIndex()
{
return RedirectToAction("Index", "Home")!;
}
protected RedirectToActionResult RedirectToPrivacy()
{
return RedirectToAction("Privacy", "Home")!;
}
protected RedirectToActionResult RedirectToError()
{
return RedirectToAction("Error", "Home")!;
}
}
}
// <auto-generated/>
namespace EndpointHelpers;
[global::Microsoft.CodeAnalysis.EmbeddedAttribute]
[global::System.AttributeUsage(
global::System.AttributeTargets.Method |
global::System.AttributeTargets.Class |
global::System.AttributeTargets.Assembly)]
internal sealed class GenerateUrlHelperAttribute : global::System.Attribute;
[global::Microsoft.CodeAnalysis.EmbeddedAttribute]
[global::System.AttributeUsage(global::System.AttributeTargets.Method)]
internal sealed class UrlHelperIgnoreAttribute : global::System.Attribute;
[global::Microsoft.CodeAnalysis.EmbeddedAttribute]
[global::System.AttributeUsage(
global::System.AttributeTargets.Method |
global::System.AttributeTargets.Class |
global::System.AttributeTargets.Assembly)]
internal sealed class GenerateLinkGeneratorAttribute : global::System.Attribute;
[global::Microsoft.CodeAnalysis.EmbeddedAttribute]
[global::System.AttributeUsage(global::System.AttributeTargets.Method)]
internal sealed class LinkGeneratorIgnoreAttribute : global::System.Attribute;
[global::Microsoft.CodeAnalysis.EmbeddedAttribute]
[global::System.AttributeUsage(
global::System.AttributeTargets.Method |
global::System.AttributeTargets.Class |
global::System.AttributeTargets.Assembly)]
internal sealed class GenerateRedirectToActionAttribute : global::System.Attribute;
[global::Microsoft.CodeAnalysis.EmbeddedAttribute]
[global::System.AttributeUsage(global::System.AttributeTargets.Method)]
internal sealed class RedirectToActionIgnoreAttribute : global::System.Attribute;
[global::Microsoft.CodeAnalysis.EmbeddedAttribute]
[global::System.AttributeUsage(global::System.AttributeTargets.Class)]
internal sealed class GenerateViewHelpersAttribute : global::System.Attribute;
[global::Microsoft.CodeAnalysis.EmbeddedAttribute]
[global::System.AttributeUsage(global::System.AttributeTargets.Method)]
internal sealed class ViewHelpersIgnoreAttribute : global::System.Attribute;
// <auto-generated/>
namespace Microsoft.CodeAnalysis
{
internal sealed partial class EmbeddedAttribute : global::System.Attribute
{
}
}
// <auto-generated/>
#nullable enable
using Microsoft.AspNetCore.Mvc;
namespace EndpointHelpers;
public sealed class HomeControllerUrlHelper(IUrlHelper url)
{
public string Index()
{
return url.Action("Index", "Home")!;
}
public string Privacy()
{
return url.Action("Privacy", "Home")!;
}
public string Error()
{
return url.Action("Error", "Home")!;
}
}
public static class UrlHelperExtensions
{
extension(IUrlHelper url)
{
public HomeControllerUrlHelper Home => new HomeControllerUrlHelper(url);
}
}
// <auto-generated/>
#nullable enable
using Microsoft.AspNetCore.Mvc;
namespace TestMVC.Controllers
{
public partial class HomeController
{
protected ViewResult IndexView()
{
return new ViewResult
{
ViewName = "Index",
ViewData = ViewData,
TempData = TempData
};
}
protected ViewResult IndexView(object? model)
{
ViewData.Model = model;
return new ViewResult
{
ViewName = "Index",
ViewData = ViewData,
TempData = TempData
};
}
protected ViewResult PrivacyView()
{
return new ViewResult
{
ViewName = "Privacy",
ViewData = ViewData,
TempData = TempData
};
}
protected ViewResult PrivacyView(object? model)
{
ViewData.Model = model;
return new ViewResult
{
ViewName = "Privacy",
ViewData = ViewData,
TempData = TempData
};
}
}
}
Useful
Download Example (.NET C#)
Share EndpointHelpers
https://ignatandrei.github.io/RSCG_Examples/v2/docs/EndpointHelpers
Category "MVC" has the following generators:
1 EndpointHelpers
2026-08-21
2 SG4MVC
2025-08-04