Sharepoint Webpart加载XSLT文件返回401

时间:2011-03-02 18:10:18

标签: sharepoint load web-parts credentials http-status-code-401

我正在尝试在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

2 个答案:

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

它有效。