12

here is my validation code:

string xsdPath = "base.xsd";
XDocument doc = XDocument.Load(xmlPath);
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("http://some.domain.org", xsdPath);
schemas.Compile();
bool isValid = true;
doc.Validate(schemas, (o, e) => {
    res.AddMessage(MessageSeverities.Error, $"{e.Severity}:{e.Message}");
    isValid = false;
});
if ( isValid ) {
    res.AddMessage(
        MessageSeverities.Notice, 
        $"{formFile.FileName} is valid!");
}

this code runs fine when used in a desktop app (.net 4.6)

the code fails when used in a .net core asp 2.1 controller with the following exception raised by schemas.Compile();:

XmlSchemaException: Type 'http://some.domain.org:tAccountingItemTypes' is not declared.

It seems that related schema files are not loaded in the asp core app. How can I force loading of related schemas ?

the schemas are:

base.xsd

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema 
    targetNamespace="http://some.domain.org" 
    xmlns="http://some.domain.org"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    elementFormDefault="qualified">

    <xs:include id="enums" schemaLocation="enums.xsd"/>

    <xs:complexType name="tAccountingLines">
      <xs:sequence>
        <xs:element name="AccountingLine" type ="tAccountingLine"></xs:element>
      </xs:sequence>
    </xs:complexType>

    <xs:complexType name="tAccountingLine">
      <xs:sequence>
        <xs:element name="AccountingType" type="tAccountingItemTypes"></xs:element>     
        </xs:element>
      </xs:sequence>    
    </xs:complexType>
</xs:schema>

enums.xsd

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema 
  targetNamespace="http://some.domain.org" 
  xmlns="http://some.domain.org"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  elementFormDefault="qualified">

  <xs:simpleType name="tAccountingItemTypes">
    <xs:restriction base="xs:string">
      <xs:enumeration value="V1"/>
      <xs:enumeration value="V2"/>
      <xs:enumeration value="V3"/>
    </xs:restriction>
  </xs:simpleType>
</xs:schema>
Charles Mager
  • 25,735
  • 2
  • 35
  • 45
tschmit007
  • 7,559
  • 2
  • 35
  • 43
  • My first guess is that it's resolving the wrong relative path - have you tried using an absolute path for `xsdPath`? e.g. `C:\path\to\base.xsd`. – Charles Mager Feb 19 '19 at 10:45
  • @CharlesMager: Yes, I come from an `XmlReader` and I'm now using a full path for `xsdPath`. – tschmit007 Feb 19 '19 at 10:47
  • 1
    You are comparing .NET Core and Full Framework behaviour, *not* ASP.NET and desktop. If your ASP.NET Core application targeted the *Full Framework* you wouldn't see any behaviour. (And yes, ASP.NET Core running on both Core and Full is confusing) – Panagiotis Kanavos Feb 19 '19 at 11:06

1 Answers1

22

I've just tried this, and the reason it doesn't load the included schema is that the resolver it uses to load it is null. This should fix it:

schemas.XmlResolver = new XmlUrlResolver();

I've done a bit of digging and found that this is a known behavioural change between Desktop & Core that is documented here:

If the schema being added imports another schema through external URI, Core does not allow resolving that URI by default while Desktop does. To allow the resolution on Core, the following needs to be called before adding the schema: AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);

Obviously, as an alternative to the switch you could explicitly set a resolver so that you're not using the default.

Charles Mager
  • 25,735
  • 2
  • 35
  • 45