Fixed values generate wrong C#
I've got an XSD with these lines in it:
…
<xs:element name="PROC-IDENT" type="xs:string" fixed="0013"/>
<xs:element name="PROC-FUNC" type="xs:string" fixed="01"/>
…
This generates:
[XmlIgnoreAttribute()]
private string procIdent = "0013";
[RequiredAttribute(AllowEmptyStrings=true)]
[XmlElementAttribute("PROC-IDENT", Form=XmlSchemaForm.Unqualified)]
public string ProcIdent
{
get
{
return procIdent;
}
set
{
procIdent = value;
}
}
[XmlIgnoreAttribute()]
private string procFunc = "01";
[RequiredAttribute(AllowEmptyStrings=true)]
[XmlElementAttribute("PROC-FUNC", Form=XmlSchemaForm.Unqualified)]
public string ProcFunc
{
get
{
return procFunc;
}
set
{
procFunc = value;
}
}
Whereas I would expect it to generate:
[RequiredAttribute()]
[XmlElementAttribute("PROC-IDENT", Form=XmlSchemaForm.Unqualified)]
public string ProcIdent { get; } = "0013";
[RequiredAttribute()]
[XmlElementAttribute("PROC-FUNC", Form=XmlSchemaForm.Unqualified)]
public string ProcFunc { get; } = "01";
Or if necessary for compatibility reasons, I'd expect it to generate:
[RequiredAttribute()]
[XmlElementAttribute("PROC-IDENT", Form=XmlSchemaForm.Unqualified)]
public string ProcIdent { get => "0013"; set { } }
[RequiredAttribute()]
[XmlElementAttribute("PROC-FUNC", Form=XmlSchemaForm.Unqualified)]
public string ProcFunc { get => "01"; set { } }
Is this caused by an error of mine, or is the fault on xscgen's side?
I assume you're referring specifically to the private setter (or lack thereof). This may be an issue in xscgen but I'm not sure if XmlSerializer is happy with a private setter when deserializing. Have you checked that it works?
I'm not sure whether this is the proper approach, but when I manually change the generated model to match the code below, it works without errors in case of a simple HTTP response deserialisation using new XmlSerializer(type).Deserialize(XmlReader.Create(await httpContent.ReadAsStreamAsync(cancellationToken)));
If I change one of the fixed values in the response XML, it still deserialises to the value of fixed in the XSD. That's fine by me, since I do not expect the remote system to violate the XSD specification they sent me. However, it might be desirable to throw in such a case instead.
[RequiredAttribute()]
[XmlElementAttribute("PROC-IDENT", Form=XmlSchemaForm.Unqualified)]
public string ProcIdent { get; } = "0013";
[RequiredAttribute()]
[XmlElementAttribute("PROC-FUNC", Form=XmlSchemaForm.Unqualified)]
public string ProcFunc { get; } = "01";
Alternative option to throw on violations (Note: The EnsureValue probably doesn't suffice for all use cases):
private void EnsureValue<T>(T fixedValue, T actualValue) {
if (fixedValue is IEquatable<T> && !fixedValue.Equals(actualValue)) { throw new XmlException("Violation of fixed value!"); }
}
[RequiredAttribute()]
[XmlElementAttribute("PROC-IDENT", Form = XmlSchemaForm.Unqualified)]
public string ProcIdent { get => "0013"; set => EnsureValue(ProcIdent, value); }
[RequiredAttribute()]
[XmlElementAttribute("PROC-FUNC", Form = XmlSchemaForm.Unqualified)]
public string ProcFunc { get => "08"; set => EnsureValue(ProcFunc, value); }
[!NOTE] This is tested in .NET 9.0 I don't know whether the
XmlSerializerin other versions behaves the same.
What issue are you seeing with the original code? Does XmlSerializer set a different value?
The information about the fixed value seems lost. But maybe I misunderstood, and the XML deserialisation is not meant to block deserialisation of invalid models?
It seems to me that I can deserialise a model which has invalid values for PROC-IDENT and PROC-FUNC and the fact that the model is not valid is lost.