RicoSuter/NSwag · error · ArgumentException
does not implement property 'Template
Error message
{type.FullName} does not implement property 'Template' What it means
RouteAttributeFacade wraps a route-like attribute and caches its 'Template' property via reflection (type.GetRuntimeProperty("Template")). If the attribute's runtime type does not expose a public 'Template' property, the facade constructor throws ArgumentException with the full type name. It is thrown when NSwag's WebApi generator encounters an attribute it treats as a route attribute but which lacks the expected surface.
Solutions
- Ensure the attribute class declares a public string property named exactly 'Template' (with getter).
- Replace the custom attribute with the standard Microsoft.AspNetCore.Mvc.RouteAttribute.
- If you must use a custom attribute, derive from RouteAttribute so Template is inherited.
- Verify with reflection that GetRuntimeProperty("Template") returns non-null for the attribute type in the failing assembly.
Example fix
// before
public class MyRouteAttribute : Attribute { public string Path { get; set; } }
// after
public class MyRouteAttribute : Attribute { public string Template { get; set; } } Defensive patterns
Strategy: validation
Validate before calling
// Verify custom route attributes expose 'Template'
var ok = typeof(MyRouteAttribute).GetRuntimeProperty("Template") != null;
if (!ok) throw new InvalidOperationException("Custom route attribute must expose public 'Template' property"); Type guard
function hasTemplateProperty(attr) {
return attr != null && typeof attr.Template === "string"; // C#: attr.GetType().GetRuntimeProperty("Template") != null
} Try / catch
try { document = generator.Generate(settings); }
catch (ArgumentException ex) when (ex.Message.Contains("does not implement property 'Template'"))
{
logger.LogError(ex, "Custom route attribute lacks 'Template' property");
} Prevention
- Derive custom route attributes from the framework's RouteAttribute.
- Never rename the 'Template' property on shared attribute base classes.
- Smoke-test document generation after any routing package upgrade.
When it happens
Trigger: Passing a custom or third-party route attribute (via UseRouteTemplate/replacement attributes or a custom controller attribute scan) whose class does not declare a public property named exactly 'Template'; inheriting from RouteAttribute in an assembly compiled against a different Microsoft.AspNetCore routing package where the property is virtual/renamed/non-public.
Common situations: Custom attribute named/behaving like a route attribute but exposing 'Name'/'Path' instead of 'Template'; package version changes making the property non-public; using an HttpMethodAttribute-derived attribute without a Template property.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- does not implement property 'Prefix
- This UI does not support multiple documents per UI: Do not…
- The SwaggerUiRoute cannot contain
- The NSwag DI services are not registered: Call…
- The OpenAPI/Swagger document
AI-assisted analysis of RicoSuter/NSwag@63daf8fcc3 (2026-09-14).
Data as JSON: /api/errors/ac4539b831701224.
Report an issue: GitHub.
Appendix: source
Thrown at src/NSwag.Generation.WebApi/Infrastructure/RouteAttributeFacade.cs:36
/// </summary>
internal sealed class RouteAttributeFacade
{
private readonly PropertyInfo _template;
private RouteAttributeFacade(Attribute attr, PropertyInfo template)
{
Attribute = attr;
_template = template;
}
public RouteAttributeFacade(Attribute attr)
{
var type = attr.GetType();
_template = type.GetRuntimeProperty("Template");
if (_template == null)
{
throw new ArgumentException($"{type.FullName} does not implement property 'Template'");
}
Attribute = attr;
}
public Attribute Attribute { get; }
public string Template => (string)_template.GetValue(Attribute);
public static RouteAttributeFacade TryMake(Attribute a)
{
var type = a.GetType();
var typeInfo = type.GetTypeInfo();
if (type.Name == "RouteAttribute" ||
typeInfo.ImplementedInterfaces.Any(i => i.Name == "IHttpRouteInfoProvider") ||
typeInfo.ImplementedInterfaces.Any(i => i.Name == "IRouteTemplateProvider")) // .NET Core
{View on GitHub (pinned to 63daf8fcc3)