I've created a custom HTMLHelper
which is supposed to render parsed XML. The method takes the XML and the path to an XSL
file and should return HTML.
When I access the page, I get the error
XmlException: For security reasons DTD is prohibited in this XML document. To enable DTD processing set the DtdProcessing property on XmlReaderSettings to Parse and pass the settings into XmlReader.Create method.
As you can see in my code below, I'm setting DtdProcessing
toParse
in the XmlReaderSettings
(as the exception suggests), which I thought would resolve the issue. On closer inspection, the exception is occurring at the line:
transformObj.Load(xsltPath);
But I can't see how I can pass XmlReaderSettings
to that method so as to set the DtdProcessing
property. The only overloads of XslCompiledTransform.Load
which accept a settings object expect a XsltSettings
object, which doesn't have a DtdProcessing
property.
The full method is as follows:
public static IHtmlContent RenderXml(this IHtmlHelper htmlHelper, string xml, string xsltPath)
{
XsltArgumentList args = new XsltArgumentList();
// Create XslCompiledTransform object to load and compile XSLT file.
XslCompiledTransform transformObj = new XslCompiledTransform();
transformObj.Load(xsltPath);
// Create XMLReaderSetting object to assign DtdProcessing, Validation type
XmlReaderSettings xmlSettings = new XmlReaderSettings();
xmlSettings.DtdProcessing = DtdProcessing.Parse;
xmlSettings.MaxCharactersFromEntities = 1024; // Prevent DoS attacks
xmlSettings.ValidationType = ValidationType.DTD;
// Create XMLReader object to Transform xml value with XSLT setting
XmlReader reader = XmlReader.Create(new StringReader(xml), xmlSettings);
using (reader)
{
StringWriter writer = new StringWriter();
transformObj.Transform(reader, args, writer);
// Generate HTML string from StringWriter
HtmlString htmlString = new HtmlString(writer.ToString());
return htmlString;
}
}
And in my view I'm using:
@Html.RenderXml(ViewBag.XML as string, ViewBag.XSL as string);
I've reviewed the advice in the answers to this question but as far as I can tell I've already taken the steps suggested. The accepted answer to this MSDN question seems to hint at an answer but I haven't been able to work out how to make use of it.