2011-03-02 40 views
1

我想在Sharepoint MOSS 2007自定义webpart中加载XSLT文件,但在尝试访问XSLT文件时出现401错误。我尝试提供默认凭据,但在调试期间检查时为空。Sharepoint Webpart加载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凭证)69 System.Xml.XmlDownloadManager.GetStream(Uri uri,ICredentials凭证)+3929007 System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri,String role,ObjectToReturn类型)+54 System.Xml.Xsl.Xslt.XsltLoader.CreateReader(Uri (XmlResolver xmlResolver)+26 System.Xml.Xsl.Xslt.XsltLoader.Load(编译器编译器,对象样式表,XmlResolver xmlResolver)+315 System.Xml.Xsl.Xslt.Compiler.Compile(对象样式表,XmlResolver xmlResolver,齐lExpression & 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(字符串stylesheetUri,XsltSettings设置,的XmlResolver stylesheetResolver)38个 NewsGallery.AjaxNewsWebPart.AjaxNewsControl.RenderContents(HtmlTextWriter的输出)403 System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter的(HtmlTextWriter编写器,ControlAdapter适配器)+32 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作家)+10 System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter作家)+32 Microsoft.SharePoint.WebPartPages.WebPart.RenderWebPart(HtmlTextWriter输出)+36 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,ControlAdapter适配器) +27 System.Web.UI.Control.RenderControl(HtmlTextWriter作家,ControlAdapter适配器)+99 System.Web.UI.Control.RenderControl(HtmlTextWriter作家)+25 Microsoft.SharePoint.WebPartPages.SPChrome.RenderPartContents(HtmlTextWriter输出,WebPart部分)+66

回答

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

我用这个方法来代替:

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(); 

和它的工作。