我正在尝试在Sharepoint MOSS 2007自定义webpart中加载XSLT文件,但在尝试访问XSLT文件时遇到401错误。我尝试提供默认凭据,但在调试期间检查时它是空的。
有谁知道如何从自定义webpart加载XSLT文件?提前谢谢。
XmlUrlResolver resolver = new XmlUrlResolver();
resolver.Credentials = CredentialCache.DefaultNetworkCredentials;
XsltSettings settings = new XsltSettings(true, true);
XslCompiledTransform oXSLTranform = new XslCompiledTransform();
string siteUrl = SPContext.Current.Site.Url;
if (siteUrl.EndsWith("/"))
siteUrl = siteUrl.Remove(siteUrl.LastIndexOf("/"));
siteUrl += "/Style Library/XSL Style Sheets/THM1News.xslt";
oXSLTranform.Load(siteUrl ,settings, resolver);
此代码返回401错误:
远程服务器返回错误:(401)未经授权。
[WebException:远程服务器返回错误:(401)未经授权。] System.Net.HttpWebRequest.GetResponse()+5313085 System.Xml.XmlDownloadManager.GetNonFileStream(Uri uri,ICredentials credentials)+69 System.Xml.XmlDownloadManager.GetStream(Uri uri,ICredentials credentials)+3929007 System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri,String role,Type ofObjectToReturn)+54 System.Xml.Xsl.Xslt.XsltLoader.CreateReader(Uri uri,XmlResolver xmlResolver)+26 System.Xml.Xsl.Xslt.XsltLoader.Load(编译器编译器,对象样式表,XmlResolver xmlResolver)+315 System.Xml.Xsl.Xslt.Compiler.Compile(对象样式表,XmlResolver xmlResolver,QilExpression& qil)+41 System.Xml.Xsl.XslCompiledTransform.CompileXsltToQil(对象样式表,XsltSettings设置,XmlResolver stylesheetResolver)+59 System.Xml.Xsl.XslCompiledTransform.LoadInternal(对象样式表,XsltSettings设置,XmlResolver stylesheetResolver)+66 System.Xml.Xsl.XslCompiledTransform.Load(String stylesheetUri,XsltSettings settings,XmlResolver stylesheetResolver)+38 NewsGallery.AjaxNewsWebPart.AjaxNewsControl.RenderContents(HtmlTextWriter输出)+403 System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer)+32 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,ControlAdapter adapter)+27 System.Web.UI.Control.RenderControl(HtmlTextWriter writer,ControlAdapter adapter)+99 System.Web.UI.Control.RenderControl(HtmlTextWriter writer)+25 System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer,ICollection children)+134 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)+19 System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer)+10 System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer)+32 Microsoft.SharePoint.WebPartPages.WebPart.RenderWebPart(HtmlTextWriter输出)+36 Microsoft.SharePoint.WebPartPages.WebPart.RenderWebPartInternal(HtmlTextWriter writer)+139 Microsoft.SharePoint.WebPartPages.WebPart.Render(HtmlTextWriter writer)+93 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,ControlAdapter adapter)+27 System.Web.UI.Control.RenderControl(HtmlTextWriter writer,ControlAdapter adapter)+99 System.Web.UI.Control.RenderControl(HtmlTextWriter writer)+25 Microsoft.SharePoint.WebPartPages.SPChrome.RenderPartContents(HtmlTextWriter输出,WebPart部分)+66
答案 0 :(得分:1)
我刚才遇到过同样的问题。这可能无法帮助您看到自您发布以来已经有一段时间,但它可能会帮助其他人。
我假设您已经消除了导致此401错误的明显情况 - 即样式库中的xslt没有已发布的主要版本或访问在用户帐户下提取xslt的webpart页面首先无法访问样式库。我还假设您有一个具有至少一个Web前端的农场环境和一个单独的数据库服务器来托管内容数据库,Web应用程序未启用匿名访问,并且身份验证方案是与NTLM集成的窗口(不是kerberos)授权和模拟已启用。
我们需要理解的是,当您从webpart代码中调用oXSLTranform.Load(xsltUrl)时,在模拟用户的凭据下运行的代码实际上是在制定带外请求(请求不直接来自浏览器)对于驻留在数据库中而不是物理上在Web服务器上的文件。如果查看发出请求的Web前端的IIS日志,您将看到正常的401.2,然后是401.1(正常的NTLM握手请求 - 响应序列),但下一个响应也将是401.1而不是预期的200.0,因为请求是使用cs-username标头为空(而不是预期的模拟用户名)。它是空的,因为无法委派此带外请求的安全上下文(因为未启用kerberos),并且由于Web应用程序也未启用匿名访问,因此拒绝具有401状态的文件请求。您需要将一个明确的网络凭据对象(如新的NetworkCredential(用户名,密码,域))传递给您的解析器以使其工作,这显然是不行的。
以下是我如何解决它......
string siteUrl = SPContext.Current.Site.Url;
SPWeb rootWeb = SPContext.Current.Site.RootWeb;
if (siteUrl.EndsWith("/"))
siteUrl = siteUrl.Remove(siteUrl.LastIndexOf("/"));
string xmlFileUrl = siteUrl + "/data.xml";
string xsltFileUrl = siteUrl + "/transform.xslt";
if (rootWeb != null)
{
var xmlDoc = new XmlDocument();
var xslDoc = new XmlDocument();
SPFile xmlDataFile = rootWeb.GetFile(xmlFileUrl); // since you are
// using the SP OM to extract the file from the doc library item you
// are going under the impersonated user credential. No need to elevate
// permissions
if (xmlDataFile != null)
{
Stream xmlDataStream = xmlDataFile.OpenBinaryStream();
xmlDoc.Load(xmlDataStream);
xmlDataStream.Close();
}
SPFile xsltTransformFile = rootWeb.GetFile(xsltFileUrl);
if (xsltTransformFile != null)
{
Stream xsltStream = xsltTransformFile.OpenBinaryStream();
xslDoc.Load(xsltStream);
xsltStream.Close();
}
// You now have your xmlDoc and xslDoc you can run your transform
// without having to provide a resolver
TransformXml(xmlDoc.outerXml, xslDoc.outerXml, false);
}
private string TransformXml(string xml, string xslt, bool bDebug)
{
StringReader xsltInput = new StringReader(xslt);
StringReader xmlInput = new StringReader(xml);
XmlTextReader xsltReader = new XmlTextReader(xsltInput);
XmlTextReader xmlReader = new XmlTextReader(xmlInput);
// Create required writer for output
StringWriter stringWriter = new StringWriter();
XmlTextWriter transformedXml = new XmlTextWriter(stringWriter);
// Create a XslCompiledTransform to perform transformation
XslCompiledTransform xsltTransform = new XslCompiledTransform(bDebug);
xsltTransform.Load(xsltReader);
xsltTransform.Transform(xmlReader, transformedXml);
}
答案 1 :(得分:1)
我改用了这种方法:
StringReader xmlReader = new StringReader(rawXML);
XPathDocument xmlDoc = new XPathDocument(xmlReader);
XslCompiledTransform myXslTransformer = new XslCompiledTransform();
XmlUrlResolver xmlResolver = new XmlUrlResolver();
xmlResolver.Credentials = CredentialCache.DefaultCredentials;
XsltSettings settings = new XsltSettings(true, true);
// Load XSL
SPSecurity.RunWithElevatedPrivileges(delegate()
{
myXslTransformer.Load(XslPath, settings, xmlResolver);
});
// Create the output stream
StringWriter sWriter = new StringWriter();
XmlTextWriter writer = new XmlTextWriter(sWriter);
// Transform
myXslTransformer.Transform(xmlDoc, null, writer);
writer.Close();
string transformedXML = sWriter.ToString();
它有效。