SharePoint跨站点显示列表出错,提示值不在预期范围内 SharePoint 2010 cross site XsltListViewWebPart error

本文介绍了一种解决SharePoint中XSLT列表视图Web部件从不同网站检索数据时出现的错误的方法。通过修改渲染上下文来确保正确引用目标网站的内容类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Web;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using WebPart = System.Web.UI.WebControls.WebParts.WebPart;

namespace XlstListModifier.XsltListViewModifier
{
    /// <summary>
    /// An error exists when an XsltListViewWebPart is retrieving its data from a List on a different SPWeb that that of the 
    /// SPContext.Current.Web. It occurs when the Microsoft.SharePoint.WebControls.NewMenu is rendered (The NewMenu is rendered 
    /// due to the default rendering of the embedded ToolbarControl in the XsltListViewWebPart. During the rendering of the NewMenu
    /// the list of SPContentType's that are used by the SPList being rendered is retrieved:
    /// 
    /// [Microsoft.SharePoint.WebControls.NewMenu.AddMenuItems()]
    /// IList<![CDATA[<SPContentType>]]> list;
    /// if (base.RenderContext.RootFolderUrl != null)
    /// {
    ///     list = new List<![CDATA[<SPContentType>]]>(this.Web.GetFolder(base.RenderContext.RootFolderUrl).ContentTypeOrder);
    /// }
    /// else
    /// {
    ///     list = new List<![CDATA[<SPContentType>]]>(this.List.RootFolder.ContentTypeOrder);
    /// }
    /// 
    /// The base.RenderContext is not null and therefore the first statement gets executed. this.Web is referencing the
    /// RenderContext.Web object (which by default uses the SPContext.Current.SPWeb (unless otherwise specified when creating)
    /// and therefore fails when the RootFolder object is for an SPList in a different SPWeb.
    /// 
    /// The code below sets the RenderContext of the ViewToolBar to the correct SPWeb, as well as setting the SPList and SPView
    /// GUID's. The property exposing the toolbar object is unfortunately an internal property though, hence the use of 
    /// reflection to access the property and set it correctly.
    /// </summary>
    [ToolboxItemAttribute(false)]
    public class XsltListViewModifier : WebPart
    {
        private bool _bFixed;
        private readonly Dictionary<Guid, SPWeb> _oWebs = new Dictionary<Guid, SPWeb>();

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            Title = "XSLT List View Modifier WebPart";
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (!_bFixed && Page.IsPostBack)
            {
                ApplyFix();
                _bFixed = true;
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            ApplyFix();
            _bFixed = true;
        }

        private void ApplyFix()
        {
            IEnumerable<XsltListViewWebPart> oParts = GetXsltParts();
            foreach (XsltListViewWebPart oPart in oParts.Where(oPart => oPart.WebId != SPContext.Current.Web.ID))
                SetToolbarContext(oPart);
        }

        /// <summary>
        /// Get an array of XsltListViewWebPart's that exist on the current WebPartPage
        /// </summary>
        /// <returns>An array of XstlListViewWebPart's</returns>
        private IEnumerable<XsltListViewWebPart> GetXsltParts()
        {
            return WebPartManager.WebParts.OfType<XsltListViewWebPart>().ToArray();
        }

        private void SetToolbarContext(XsltListViewWebPart part)
        {
            try
            {
                //Get hold of the toolbar that renders the new menu items
                ViewToolBar oTbar = GetPrivatePropertyValue<ViewToolBar>(part, "ToolbarControl");
                if (oTbar == null) return;

                //We keep a collection of SPWeb objects in case there is more than on XsltListViewWebPart on
                //the page looking at lists in more than one site (SPWeb). This way we don't instanciate more
                //than one SPWeb for each SPWeb needed
                SPWeb oWb;
                if (_oWebs.ContainsKey(part.WebId))
                {
                    oWb = _oWebs[part.WebId];
                }
                else
                {
                    oWb = SPContext.Current.Site.OpenWeb(part.WebId);
                    _oWebs.Add(part.WebId, oWb);
                }
                
                //Create the SPContext object that references the correct SPList, SPView and most importantly..SPWeb
                SPContext oCtx = SPContext.GetContext(HttpContext.Current, new Guid(part.ViewGuid), part.ListId, oWb);
                //Set the RenderContext of the ToolbarControl
                oTbar.RenderContext = oCtx;
            }
            catch (Exception)
            { }
        }

        public override void Dispose()
        {
            base.Dispose();

            //Ensure that any webs are disposed of incase the GC doesn't pick it up during object disposal
            foreach (Guid oId in _oWebs.Keys) _oWebs[oId].Dispose();
        }

        public static T GetPrivatePropertyValue<T>(object o, string name)
        {
            if (o == null) throw new ArgumentNullException("o");
            PropertyInfo oInfo = o.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            if (oInfo == null) throw new ArgumentOutOfRangeException("name", string.Format("Property {0} was not found in Type {1}", name, o.GetType().FullName));
            return (T)oInfo.GetValue(o, null);
        }
    }
}


参考地址:SharePoint 2010 cross site XsltListViewWebPart error


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值