Question

On my document set homepage I have added two list view web parts.

These two web parts are connected so the second is filtered based on the first.

enter image description here

Environment 1 is selected by default on page load. The problem I have is when I select Environment 2 or Environment 3, I see an error message:

enter image description here

The interesting messages in the ULS logs:

Name=Request (POST:[site]/Applications/Forms/Application/docsethomepage.aspx?View=%7B152431A0%2D9A5D%2D499F%2D8789%2D7A67608F64C3%7D&SelectedID=3&ID=4)

And...

Application error when access [site]/Applications/Forms/Application/docsethomepage.aspx, Error=Object reference not set to an instance of an object.
at Microsoft.Office.Server.WebControls.DocSetWelcomePageControl.BuildV15BreadcrumbScript()
at Microsoft.Office.Server.WebControls.DocSetWelcomePageControl.RenderBreadcrumb()
at Microsoft.Office.Server.WebControls.DocSetWelcomePageControl.RenderControl(HtmlTextWriter writer)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at Microsoft.SharePoint.WebControls.AjaxDelta.RenderChildren(HtmlTextWriter output)
at System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer)
at System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer)
at Microsoft.SharePoint.WebControls.AjaxDelta.Render(HtmlTextWriter writer)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter writer)
at System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer)
at Microsoft.SharePoint.WebControls.SharePointForm.Render(HtmlTextWriter output)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
at System.Web.UI.Page.Render(HtmlTextWriter writer)
at Microsoft.SharePoint.WebControls.DeltaPage.RenderToBase(HtmlTextWriter writer)
at Microsoft.SharePoint.WebControls.DeltaPage.Render(HtmlTextWriter writer)
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

And...

System.NullReferenceException: Object reference not set to an instance of an object. at Microsoft.Office.Server.WebControls.DocSetWelcomePageControl.BuildV15BreadcrumbScript() at Microsoft.Office.Server.WebControls.DocSetWelcomePageControl.RenderBreadcrumb() at Microsoft.Office.Server.WebControls.DocSetWelcomePageControl.RenderControl(HtmlTextWriter writer) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at Microsoft.SharePoint.WebControls.AjaxDelta.RenderChildren(HtmlTextWriter output) at System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer) at System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer)
at Microsoft.SharePoint.WebControls.AjaxDelta.Render(HtmlTextWriter writer) at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter writer) at System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) at Microsoft.SharePoint.WebControls.SharePointForm.Render(HtmlTextWriter output) at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.Page.Render(HtmlTextWriter writer) at Microsoft.SharePoint.WebControls.DeltaPage.RenderToBase(HtmlTextWriter writer) at Microsoft.SharePoint.WebControls.DeltaPage.Render(HtmlTextWriter writer) at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

My guess is when I select Environment 2 the javascript is trying to change the URL to the one specified in the first error message above, but then this is causing a problem showing the document set because it's removing the query string parameters that are normally present on a document set homepage.

For info, the URL to the document set homepage is:

[site]/Applications/Forms/Application/docsethomepage.aspx?ID=4&FolderCTID=0x0120D52000097B2AAED9957E4CAD8855E43B2B0C6F00341030E5B70A6A4D9C605B8C48983359&List=3d911efd-eed7-4019-86c3-ed109b796891&RootFolder=[site]%2FApplications%2FTest%20app%202&RecSrc=[site]%2FApplications%2FTest%20app%202

When I hover over the arrows in the Select column, this is the URL I see:

javascript:SelectField('{152431A0-9A5D-499F-8789-7A67608F64C3}','3');return false;

If this is indeed a URL and query string problem, is there a way I can tap into this javascript function and prevent it from stripping all the query string parameters?

UPDATE

I should have added that the URL on the error page is this:

[site]/Applications/Forms/Application/docsethomepage.aspx?View=%7B152431A0-9A5D-499F-8789-7A67608F64C3%7D&SelectedID=3&ID=4

So it does look like the SelectField function is stripping the query string parameters that are necessary for the document set homepage to display correctly.

But then the next question is, if I was to change the URL manually, what can I put in for this to work? I have already tried:

[site]/Applications/Forms/Application/docsethomepage.aspx?ID=4&FolderCTID=0x0120D52000097B2AAED9957E4CAD8855E43B2B0C6F00341030E5B70A6A4D9C605B8C48983359&List=3d911efd-eed7-4019-86c3-ed109b796891&RootFolder=[site]%2FApplications%2FTest%20app%202&RecSrc=[site]%2FApplications%2FTest%20app%202&View=%7B152431A0-9A5D-499F-8789-7A67608F64C3%7D&SelectedID=3&ID=4

But strangely, this just navigates to the root of the Applications document library.

Was it helpful?

Solution

If you want to manually navigate to the doc set, here's the correct URL:

[site]/Applications/Forms/Application/docsethomepage.aspx?ID=4&FolderCTID=0x0120D52000097B2AAED9957E4CAD8855E43B2B0C6F00341030E5B70A6A4D9C605B8C48983359&List=3d911efd-eed7-4019-86c3-ed109b796891&RootFolder=[site]%2FApplications%2FTest%20app%202&RecSrc=[site]%2FApplications%2FTest%20app%202&View=%7B152431A0-9A5D-499F-8789-7A67608F64C3%7D&SelectedID=3

Note that I removed the final ID=4: it's already present as the first parameter. That's the one that defines the doc set to display. If it's duplicated, the doc set selection fails, and the page falls back to the root of the doc lib.
Also that once you've navigated with the above-mentioned URL, you can change the provider selection, strangely with no error anymore!

EDIT
OK, I finally managed to make it work.

  1. First, edit your Doc Set page, and add a Script Editor Web part
  2. Edit the Snippet of the Script WP and add this code:

    <script type='text/javascript'>
    
    function MyCustomSelectField(view, selectID) {
    var strDocUrl = ajaxNavigate.get_href();
    var strHash = ajaxNavigate.get_hash();
    var fViewReplaced = false;
    var pattern = /\#.*/i;
    
    strDocUrl = strDocUrl.replace(pattern, "");
    var viewGuid = GetUrlKeyValue("View", true);
    var pageView = GetUrlKeyValue("PageView", true);
    var idForm = GetUrlKeyValue("ID", true);
    var contentTypeIdForm = GetUrlKeyValue("ContentTypeId", true);
    
    if (view.toUpperCase() != viewGuid.toUpperCase()) {
        var encodedView = escapeProperly(view);
    
        if (encodedView.toUpperCase() != viewGuid.toUpperCase()) {
            pattern = /\?[^?]*/i;
            var idxQuery = strDocUrl.indexOf("?");
    
            if (idxQuery != -1) {
                var idxView = strDocUrl.indexOf("View=", idxQuery);
                if(idxView != -1)
                    strDocUrl = strDocUrl.replace(/\?.*View=[^&]*/, "View=" + encodedView);
                else
                    strDocUrl = strDocUrl + "&View=" + encodedView;
            }
            else
                strDocUrl = strDocUrl + "?View=" + encodedView;
            fViewReplaced = true;
        }
    }
    if (!fViewReplaced && GetUrlKeyValue("SelectedID") != "") {
        var selectIDOld = /&SelectedID=[^&]*/gi;
    
        strDocUrl = strDocUrl.replace(selectIDOld, "");
        selectIDOld = /\?SelectedID=[^&]*&?/;
        strDocUrl = strDocUrl.replace(selectIDOld, "?");
    }
    strDocUrl = strDocUrl + "&SelectedID=";
    strDocUrl = strDocUrl + selectID;
    if (fViewReplaced && pageView != "") {
        strDocUrl = strDocUrl + "&PageView=" + pageView;
    }
    if (idForm != "") {
        strDocUrl = strDocUrl + "&ID=" + idForm;
    }
    if (contentTypeIdForm != "") {
        strDocUrl = strDocUrl + "&ContentTypeId=" + contentTypeIdForm;
    }
    if (strHash != "") {
        strDocUrl = strDocUrl + strHash;
    }
    _SubmitFormPost(strDocUrl);
    return false;
    }
    
    var oldCoreInvoke = CoreInvoke;
    CoreInvoke = function (fn) {
    if (fn == '_SelectField')
        MyCustomSelectField(arguments[1], arguments[2]);
    else
        oldCoreInvoke.apply(this, arguments);
    }
    
    </script>
    
  3. Close the page, test :)

What it does (OK, its not that clean, but when it comes to bugs in default JavaScript files, you don't really have choice :(...):

  1. It overrides the default SelectField function. To do this, we also override CoreInvoke (at the end of the code above). Indeed, CoreInvoke dynamically calls default SelectField. So we needed to override it as well.
  2. The new SelectField (MyCustomSelectField) changes:

    if (idxQuery != -1)
        strDocUrl = strDocUrl.replace(pattern, "?View=" + encodedView);
    else
        strDocUrl = strDocUrl + "?View=" + encodedView;
    

    (where the problem was lying, since strDocUrl.replace(pattern... removed all the current query string) to:

     if (idxQuery != -1) {
        var idxView = strDocUrl.indexOf("View=", idxQuery);
        if(idxView != -1)
            strDocUrl = strDocUrl.replace(/\?.*View=[^&]*/, "View=" + encodedView);
        else
            strDocUrl = strDocUrl + "&View=" + encodedView;
    }
    else
        strDocUrl = strDocUrl + "?View=" + encodedView;
    

EDIT 2
A new version of the JavaScript code, that should avoid all duplicates in the query string:

<script type='text/javascript'>
// Add / Update a key-value pair in the URL query parameters
function updateUrlParameter(uri, key, value) {
    // remove the hash part before operating on the uri
    var i = uri.indexOf('#');
    var hash = i === -1 ? '' : uri.substr(i);
    uri = i === -1 ? uri : uri.substr(0, i);

    var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
    var separator = uri.indexOf('?') !== -1 ? "&" : "?";
    if (uri.match(re)) {
        uri = uri.replace(re, '$1' + key + "=" + value + '$2');
    } else {
        uri = uri + separator + key + "=" + value;
    }
    return uri + hash;  // finally append the hash as well
}


function MyCustomSelectField(view, selectID) {
    var strDocUrl = ajaxNavigate.get_href();

    strDocUrl = updateUrlParameter(strDocUrl, "View", view);
    strDocUrl = updateUrlParameter(strDocUrl, "SelectedID", selectID);

    _SubmitFormPost(strDocUrl);
    return false;
}


var oldCoreInvoke = CoreInvoke;
    CoreInvoke = function (fn) {
        if (fn == '_SelectField')
            MyCustomSelectField(arguments[1], arguments[2]);
        else
            oldCoreInvoke.apply(this, arguments);
    }
</script>
Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top