Blog has moved

Posted: February 27, 2014 in Uncategorized

I have created my new blog on Sharepoint Online using HTML 5 and bootstrap framework to make it responsive. After some weeks of html , css and js development, you have it here.

https://levalencia-public.sharepoint.com/

I will be moving my posts from this blog to my new one, and stop posting here, please update your bookmarks and rss feed.

In my current project, we have a page on the root web of every site collection (18,000 site collections), every welcome page has 2 webparts which renders the last created sites.

We have 2 types of sites, jobs and opportunities.  This information in saved in the property bag under the key “WebProperty”.

The requirement is to show the last 5 created sites of each type.

This code is as I had it before.

private void LoadGridData()
        {
            try
            {
                String currentUrl = SPContext.Current.Site.Url;

                var jobInfoList = new List<JobInfo>();

                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (var clientSiteCollection = new SPSite(currentUrl))
                    {
                        foreach (
                            SPWeb web in
                                clientSiteCollection.AllWebs.Where(
                                    c =>
                                    c.AllProperties[Constants.WebProperties.General.WebTemplate] != null &&
                                    c.AllProperties[Constants.WebProperties.General.WebTemplate].ToString() ==
                                    Constants.WebTemplates.JobWebPropertyName).OrderByDescending(d => d.Created).Take(5)
                            )
                        {
                            if (web.DoesUserHavePermissions(SPContext.Current.Web.CurrentUser.LoginName,
                                SPBasePermissions.Open))
                            {
                                SPList jobInfoListSp = web.Lists.TryGetList(Constants.Lists.JobInfoName);
                                if (jobInfoListSp != null)
                                {
                                    if (jobInfoListSp.Items.Count > 0)
                                    {
                                        var value =
                                            new SPFieldUrlValue(
                                                jobInfoListSp.Items[0][Constants.FieldNames.Job.iPowerLink].ToString());

                                        jobInfoList.Add(new JobInfo
                                        {
                                            JobName =
                                                jobInfoListSp.Items[0][Constants.FieldNames.Job.JobName].ToString(),
                                            JobCode =
                                                jobInfoListSp.Items[0][Constants.FieldNames.Job.JobCode].ToString(),
                                            IPowerLink = value.Url,
                                            JobWebsite = web.Url,
                                            IsConfidential =
                                                HelperFunctions.ConvertToBoolean(
                                                    jobInfoListSp.Items[0][Constants.FieldNames.Job.Confidential]
                                                        .ToString())
                                        });
                                    }
                                }
                            }

                            web.Dispose();
                        }
                    }
                });

                _lastCreatedJobsGrid.DataSource = jobInfoList;
                _lastCreatedJobsGrid.DataBind();
            }
            catch (Exception ex)
            {
                LoggingService.LogError(LoggingCategory.Job, ex);
            }
        }


Well, you can see there is a Dispose() inside the foreach, that is not the problem, the problem is the AllWebs.

So, I dig deep into it and I found the following link : http://solutionizing.net/2009/01/05/linq-for-spwebcollection-revisited-assafeenumerable/

So, I replaced the AllWebs with AllWebs.AsSafeEnumerable().

Then, the memory leak went away.

But guess what, this code introduced another problem.

53b416d1-1497-4b40-beb5-cd261180ece8 Stack trace:   
 at Microsoft.SharePoint.SPWeb.get_Created()    
 at xx.SP.DMS.WebParts.WebParts.LastCreatedJobs.LastCreatedJobs.<>c__DisplayClass8.<LoadGridData>b__7(SPWeb d)    
 at System.Linq.EnumerableSorter`2.ComputeKeys(TElement[] elements, Int32 count)    
 at System.Linq.EnumerableSorter`1.Sort(TElement[] elements, Int32 count)    
 at System.Linq.OrderedEnumerable`1.<GetEnumerator>d__0.MoveNext()    
 at System.Linq.Enumerable.<TakeIterator>d__3a`1.MoveNext()    
 at xx.SP.DMS.WebParts.WebParts.LastCreatedJobs.LastCreatedJobs.<>c__DisplayClass8.<LoadGridData>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 xx.SP.DMS.WebParts.WebParts.LastCreatedJobs.LastCreatedJobs.LoadGridData()    
 at xx.SP.DMS.WebParts.WebParts.LastCreatedJobs.LastCreatedJobs.OnPreRender(EventArgs e)    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Control.PreRenderRecursiveInternal()    
 at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)    
 at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)    
 at System.Web.UI.Page.ProcessRequest()    
 at System.Web.UI.Page.ProcessRequest(HttpContext context)    
 at Microsoft.SharePoint.Publishing.TemplateRedirectionPage.ProcessRequest(HttpContext context)    
 at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()    
 at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)    
 at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)    
 at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)    
 at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)    
 at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)    
 at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)    
 at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)    
 at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)    
 at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)    
 at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)

When I debugged line by line, my catches were no hit, but then I saw that my new method AsSafeEnumerable(), didnt have a catch. just a finally, so I guessed there was an exception there, just not caught.

My good friends here helped me to find the problem, apparently the .Where from Linq and the .Take, are not “Safe” with SPWeb objects, so extension methods had to be done to overcome this error.

See original question here:
http://stackoverflow.com/questions/21756403/error-on-system-linq-enumerable-takeiteratord-3a1-movenext

I fixed the problem by creation these 2 methods.

public static IEnumerable<TSource> SafeTake<TSource>(
    this IEnumerable<TSource> source,
    int count
) where TSource : IDisposable
{
    foreach(var item in source)
    {
        if(--count >= 0)
        {
            yield return item;
        }
        else if (item != null)
        {
            item.Dispose();
        }
    }
}

public static IEnumerable<TSource> SafeWhere<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate
) where TSource: IDisposable
{
    return source.SelectMany(x => {
        var result = predicate(x);
        if(!result && x != null) x.Dispose();
        return Enumerable.Repeat(x, result ? 1 : 0);
    });
}

And then of course replacing the Where with SafeWher and the Take with SafeTake


foreach (var web in clientSiteCollection.AllWebs.SafeWhere(
c =>
c.AllProperties[Constants.WebProperties.General.WebTemplate] != null &&
c.AllProperties[Constants.WebProperties.General.WebTemplate].ToString() ==
Constants.WebTemplates.JobWebPropertyName).OrderByDescending(d => d.Created).SafeTake(5)
)
 

All Sharepoint developers have seen sometimes this:

An SPRequest object was not disposed before the end of this thread.  To avoid wasting system resources, dispose of this object or its parent (such as an SPSite or SPWeb) as soon as you are done using it.  This object will now be disposed.

And normally if you are a good one, you know how to fix it in the code you developed.   But, what about if you did not develop the code and you are trying to troubleshoot performance problems and memory leak. By default the ULS Logs only shows the page, but it wont show the methods, of the page that have the memory leak.   You can activate this with the following script.

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue [System.Reflection.Assembly]::LoadFile($Env:CommonProgramFiles+”Microsoft SharedWeb Server Extensions14ISAPIMicrosoft.SharePoint.dll”) | out-null # Get Content Service of the farm $contentService = [Microsoft.SharePoint.Administration.SPWebService]::ContentService # Display and change the setting of property “CollectSPRequestAllocationCallStacks” write-host “Current: ” $contentService.CollectSPRequestAllocationCallStacks $contentService.CollectSPRequestAllocationCallStacks = $true $contentService.Update() write-host ” New: ” $contentService.CollectSPRequestAllocationCallStacks

Today, I had this error when I was trying to deploy a simple Hello World App for first time.

I tried everything on this blog and still didnt work.

http://blog.mannualag.com/2013/03/07/nuisances-of-starting-developing-apps-for-sharepoint-2013/#

Guys, let me tell you what my problem was.

 

When I first started I was developing with the farm account, suddently when I was trying to deploy VS says that you can not use the system account to deploy apps. Read the link above.

So, I logged in with my account, and the mistake was this:  I created the app management service application and the new web application with my username, yes its farm admin, yes its local administrator.

The problem is the farm account has a server role of db creation and security admin, this means that when this account tries to create databases, it will also make the security adjustments needed on the databases for the configuration to be correct.

Because I tried to do this with a normal user account which has no Sql Server roles, then the Content DB was created, and the app management service application was created too.

 

However, it didnt set up the security on the databases the right way

 

After following the post above, and checking the logs with the dba we saw this error :

There is a compatibility range mismatch between the Web server and database

 

We double checked permissions and they were all set correctly.

 

Solution:

1. Delete the app management service application.

2. Delete the new web application content database.

 

Fortunately it was a development environment, after recreating these 2 things, the app was succesfully deployed using F5 on Vs 2012.

 

 

 

This question comes from Twitter from: Kyle Redddock, @WinPhanKyle

He wanted to know how to change the group name of the site columns through central admin.

 

This is not possible through central admin but its pretty easy through powershell.

The first thing you have to know is that you can not create a group of columns, the group name is actually a property of the site column itself, and once you change all the group names of your site columns, then you will all the columns grouped under a different group (if that makes sense)

 

$site = new-object Microsoft.SharePoint.SPSite(“http://xxxx:4000”);

$site.rootweb.Fields[“TheColumnName”].Group = “TheNewGroupTitle”;

$site.rootweb.Fields[“TheColumnName”].Update();

Today, I had this on my enterprise environment which was not easy to figure out.

All our environments should be the same, but apparently it was not the case for the test environment.

Because we are trying to align together all our environments, we backed up one content database from prod and restore it into the test environment, and one of the pages didnt work showing the error: Property doesn’t exist or is used in a manner inconsistent with schema settings.

This page has a content search webpart with a very easy query:

contentclass:”STS_ListItem”  {SearchBoxQuery} ParentLink:”*opportunityinfo*”

 

As you can see the query is using OOTB managed properties, then I thought, wtf, I am screwed up, I checked the ULS logs and I saw:

 

SearchServiceApplicationProxy::Execute–Error occured: System.ServiceModel.FaultException`1[Microsoft.Office.Server.Search.Administration.SearchServiceApplicationFault]: SortList (Fault Detail is equal to Microsoft.Office.Server.Search.Administration.SearchServiceApplicationFault).
Getting results failed: SortList
Failed to get document content data. System.ComponentModel.Win32Exception (0×80004005): Cannot complete this function at Microsoft.SharePoint.SPSqlClient.GetDocumentContentRow(Int32 rowOrd, Object ospFileStmMgr, SPDocumentBindRequest& dbreq, SPDocumentBindResults& dbres)

Could not get DocumentContent row: 0×80004005.

SearchServiceApplicationProxy::GetUpdatedQueryParameterSpecifications–Proxy Name:Search Service Application Proxy EndPoint: http://be-xxxxx:32843/69cb3b7380164049ba43d8679204fb85/SearchService.svc

 

From the ULS Logs, all entries were high except Getting results failed: SortList, so I immediately checked the SORTING tab. And there it was.  The sort field was empty, why? because the managed property did not exist on the test environment.

 

I created the managed property and voila!!!, I fixed the problem!

 

I am a genius!

 

My Tasks Aggregation in SharePoint Server and Exchange Task Integration.