{"record":{"id":"ac4539b831701224","repo":"RicoSuter/NSwag","slug":"type-fullname-does-not-implement-property-template","errorCode":null,"errorMessage":"{type.FullName}  does not implement property 'Template'","messagePattern":"(.+?)  does not implement property 'Template'","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/NSwag.Generation.WebApi/Infrastructure/RouteAttributeFacade.cs","lineNumber":36,"sourceCode":"    /// </summary>\n    internal sealed class RouteAttributeFacade\n    {\n        private readonly PropertyInfo _template;\n\n        private RouteAttributeFacade(Attribute attr, PropertyInfo template)\n        {\n            Attribute = attr;\n            _template = template;\n        }\n\n        public RouteAttributeFacade(Attribute attr)\n        {\n            var type = attr.GetType();\n\n            _template = type.GetRuntimeProperty(\"Template\");\n            if (_template == null)\n            {\n                throw new ArgumentException($\"{type.FullName}  does not implement property 'Template'\");\n            }\n\n            Attribute = attr;\n        }\n\n        public Attribute Attribute { get; }\n\n        public string Template => (string)_template.GetValue(Attribute);\n\n        public static RouteAttributeFacade TryMake(Attribute a)\n        {\n            var type = a.GetType();\n            var typeInfo = type.GetTypeInfo();\n\n            if (type.Name == \"RouteAttribute\" ||\n                typeInfo.ImplementedInterfaces.Any(i => i.Name == \"IHttpRouteInfoProvider\") ||\n                typeInfo.ImplementedInterfaces.Any(i => i.Name == \"IRouteTemplateProvider\")) // .NET Core\n            {","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/RicoSuter/NSwag/blob/63daf8fcc3a25151b62eb4b326a1e8ea048a0d41/src/NSwag.Generation.WebApi/Infrastructure/RouteAttributeFacade.cs#L18-L54","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\npublic class MyRouteAttribute : Attribute { public string Path { get; set; } }\n\n// after\npublic class MyRouteAttribute : Attribute { public string Template { get; set; } }","handlingStrategy":"validation","validationCode":"// Verify custom route attributes expose 'Template'\nvar ok = typeof(MyRouteAttribute).GetRuntimeProperty(\"Template\") != null;\nif (!ok) throw new InvalidOperationException(\"Custom route attribute must expose public 'Template' property\");","typeGuard":"function hasTemplateProperty(attr) {\n  return attr != null && typeof attr.Template === \"string\"; // C#: attr.GetType().GetRuntimeProperty(\"Template\") != null\n}","tryCatchPattern":"try { document = generator.Generate(settings); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"does not implement property 'Template'\"))\n{\n    logger.LogError(ex, \"Custom route attribute lacks 'Template' property\");\n}","preventionTips":["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."],"tags":["reflection","webapi","route-attribute","nswag"],"backgroundTag":"missing-required-argument","analyzedSha":"63daf8fcc3a25151b62eb4b326a1e8ea048a0d41","analyzedAt":"2026-09-14T11:38:15.205Z","contentChangedAt":"2026-09-14T11:38:15.205Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}