Friday, July 25, 2014

Access denied while the code accessed the property named MyWeb.Navigation.UseShared in SharePoint 2013

I don't know the reason why it took a long time for me to fix the issue in SharePoint 2013. I don't know whether my SharePoint developing skill is down or not and I think I am too old to work as a developer.

My situation is:
Step 1: Backup database of web application in SharePoint 2010
Step 2: Attach this database into SharePoint 2013
Step 3: Upgrade the site

Result:
Everything worked correctly accept for the home page throw the error "Access denied". They show "this page is not shared with you!"

The home is inherited the custom master page and using the custom code to add the navigation to top link bar.

This is a code:

            MyWeb.AllowUnsafeUpdates = true;

            if (!MyWeb.IsRootWeb)
            {
                MyWeb.Navigation.UseShared = true;

                if (!MyWeb.ParentWeb.Navigation.UseShared)
                {
                    // Get top link bar.
                    SPNavigationNodeCollection topnav = MyWeb.ParentWeb.Navigation.TopNavigationBar;

                    serverRelativeUrl = MyWeb.ServerRelativeUrl;

                    // Query for an existing link.
                    SPNavigationNode node = topnav
                        .Cast<SPNavigationNode>()
                        .FirstOrDefault(n => n.Url.Equals(serverRelativeUrl));

                    // No link, so add one.
                    if (node == null)
                    {
                        // Truncate long a title.
                        string linkTitle = MyWeb.Title;
                        if (linkTitle.Length > 15)
                            linkTitle = linkTitle.Substring(0, 12) + "...";

                        // Create the node.
                        node = new SPNavigationNode(linkTitle, serverRelativeUrl);

                        // Add it.
                        node = topnav.AddAsLast(node);
                    }
                }
            }

            MyWeb.AllowUnsafeUpdates = false;

You know what,  the property named "MyWeb.Navigation.UseShared" is only work with Design role assignment or higher. If I logged into site by contributor, it will throw exception "Access denied".

This is error tracking:

System.Threading.ThreadAbortException: Thread was being aborted.   at System.Threading.Thread.AbortInternal()   at System.Threading.Thread.Abort(Object stateInfo)   at System.Web.HttpResponse.AbortCurrentThread()   at Microsoft.SharePoint.Utilities.SPUtility.Redirect(String url, SPRedirectFlags flags, HttpContext context, String queryString)   at Microsoft.SharePoint.Utilities.SPUtility.RedirectToAccessDeniedPage(HttpContext context)   at Microsoft.SharePoint.Utilities.SPUtility.HandleAccessDenied(HttpContext context)   at Microsoft.SharePoint.Utilities.SPUtility.HandleAccessDenied(Exception ex)   at Microsoft.SharePoint.SPSecurableObject.CheckPermissions(SPBasePermissions permissionMask)   at Microsoft.SharePoint.SPSecurity.ValidateSecurityOnOperation(SPOperationCode code, SPSecurableObject obj)   at Microsoft.SharePoint.SPSecurityOnOperationScope..ctor(SPOperationCode code, SPSecurableObject obj)   at Microsoft.SharePoint.Navigation.SPNavigation.set_UseShared(Boolean value)   at Bamboo.CommunityCentral.MasterPageBase.<AddCentralSiteToTopLinkBar>b__5()   at Microsoft.SharePoint.SPSecurity.<>c__DisplayClass5.<RunWithElevatedPrivileges>b__3()   at Microsoft.SharePoint.Utilities.SecurityContext.RunAsProcess(CodeToRunElevated secureCode)   at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(WaitCallback secureCode, Object param)   at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(CodeToRunElevated secureCode)   at Bamboo.CommunityCentral.MasterPageBase.AddCentralSiteToTopLinkBar()   at Bamboo.CommunityCentral.MasterPageBase.OnLoad(EventArgs e)

Remember: That code cannot work under privileged delegation, thus there is one way to pass the error is to check the current user before apply the code.

Good luck to you.

Monday, July 14, 2014

[Resolved] Error: Unable to get value of the property 'showWaitScreenWithNoClose': object is null or undefined

Today, I will try to use the API with a wide library JS in SharePoint 2013. If you are familiar to JS and SharePoint Client Object Model, you will know how to call a method or execute a query using SharePoint API. However, to work with SharePoint 2013 smoothly, you must research what the SharePoint did!

In some js library, SharePoint had supported a debug file to help you learn to be acquainted with approaching API client library. And I have resolved a great of issues based on that.

My use case is: when I click on a post-back button, after the back-end processed and return the data, the page is reload and I don't want to submit as a post-back re-rendering all view state. The code looks like:

<asp:Button runat="server" Text="Process..." OnClientClick="Update()" OnClick="btn_ProcessClick"></asp:Button>

and the Js code is:

function Update() {
        var dialog = SP.UI.ModalDialog.showWaitScreenWithNoClose("Waiting!", "Processing...");
}

I did not implement any remaining functions, just need to test a window dialog to ensure the dialog works fine. But the result is:

Error: Unable to get value of the property 'showWaitScreenWithNoClose': object is null or undefined



My though is all client scripts are loaded and SharePoint did by using the default master page. And that's true! However, to initialize the object or class we must ensure the script loaded into page before using. To fix this issue, the code was changed:

var fn = function() {
        var dlg = SP.UI.ModalDialog.showWaitScreenWithNoClose("Waiting!", "Processing...");
};
var defd;

try {
     defd = typeof SP.UI.ModalDialog.showWaitScreenWithNoClose;
}
 catch (e) {
        defd = "undefined";
}
EnsureScript("SP.UI.Dialog.js", defd, fn);

And the result is:


Conclusion: To work with API client SharePoint object model, we must ensure the scripts loaded!