dotnet/wpf · error · XamlXmlWriterException
SR.ExpandPositionalParametersinTypeWithNoDefaultConstructor
Error message
SR.ExpandPositionalParametersinTypeWithNoDefaultConstructor
What it means
Same failure mode as the positional-parameter expansion guard but reached from the property-expansion path: when expanding a markup extension written with property syntax (or implicit members) XamlXmlWriter needs to instantiate the extension type, and if containingType.ConstructionRequiresArguments is true (no default constructor) it throws XamlXmlWriterException ExpandPositionalParametersinTypeWithNoDefaultConstructor at this site.
Solutions
- Add a public parameterless constructor to the markup extension class
- Serialize the extension with attribute/explicit property syntax that avoids the expansion path
- Provide a custom XamlValueConverter/type mapping so the writer does not need to instantiate the type
Example fix
// before
public class MyExt : MarkupExtension { public MyExt(int n) {...} } // throws on expansion
// after
public class MyExt : MarkupExtension {
public MyExt() {}
public MyExt(int n) {...}
} Defensive patterns
Strategy: validation
Validate before calling
if (extType != null && extType.ConstructionRequiresArguments && expansionNeeded) throw new InvalidOperationException("Markup extension must have a default constructor for expansion"); Type guard
bool CanExpandMarkupExtension(XamlType t) => t == null || !t.ConstructionRequiresArguments;
Try / catch
try { writer.WriteNode(reader); }
catch (XamlXmlWriterException ex) when (ex.Message.Contains("DefaultConstructor")) { /* serialize with named properties instead */ } Prevention
- Always include a parameterless constructor on MarkupExtension subclasses
- Prefer settable properties over required constructor arguments in serializable extensions
- Smoke-test save/load round-trips for every custom extension
When it happens
Trigger: Writing a markup extension with expansion required (property-element expansion path at line ~1181) where the containing markup-extension XamlType lacks a default constructor (ConstructionRequiresArguments true).
Common situations: Custom MarkupExtension classes without parameterless constructors; refactors that added required constructor arguments; serialization of extensions used in templates/styles that forces expansion.
Related errors
- ArgumentNullException(nameof(arrayType))
- ArgumentNullException(nameof(member))
- SR.PositionalArgumentsWrongLength
- ArgumentNullException(nameof(assemblyNames))
- ArgumentNullException(nameof(contentType))
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/9b256f884c8c85a6.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlXmlWriter.cs:1181
writer.namespaceScopes.Push(new Frame
{
AllocatingNodeType = XamlNodeType.StartMember,
Type = writer.namespaceScopes.Peek().Type,
Member = property
});
XamlType containingType = writer.namespaceScopes.Peek().Type;
if (property == XamlLanguage.PositionalParameters)
{
// the writer is not in a state where it can write markup extensions in curly form
// so it expands the positional parameters as properties.
writer.namespaceScopes.Pop();
// but in order to expand properties, the markup extension needs to have a default constructor
if (containingType is not null && containingType.ConstructionRequiresArguments)
{
throw new XamlXmlWriterException(SR.ExpandPositionalParametersinTypeWithNoDefaultConstructor);
}
writer.ppStateInfo.ReturnState = State;
writer.currentState = ExpandPositionalParameters.State;
}
else if (IsImplicit(property))
{
// Stop trying attributes
writer.WriteDeferredNamespaces(XamlNodeType.StartObject);
writer.currentState = InMember.State;
}
else if (property == containingType.ContentProperty)
{
writer.currentState = TryContentPropertyInTryAttributesState.State;
}
else if (property.IsDirective && (property.Type is not null && (property.Type.IsCollection || property.Type.IsDictionary)))
{View on GitHub (pinned to 81131a70a4)