Dealing with the "No parameterless constructor defined for this object" on 'changed' Page Layout

August 13th, 2009 by undercoverlaptop

When we initially launched one of our publishing page layouts, we had a Page Layout that contained a third party web part. After launch, we realized that this web part either needed to be updated or ripped out, so for the time being, we ripped out the web part (uninstall, the whole nine yards). However, we still needed to use the Page Layout, just without the web parts pre-defaulted on the page. Low and behold, the first time we try to create the Page Layout, we get the "No parameterless constructor defined for this object".

It appears that a few people have been having this issue and some people were saying that they could resolve the issue by deleting the Page Layout from the Master Page library but this wouldn't work for me because I still had some pages that inherited from the layout. After some additional research, I discovered that you can go into Web Part Maintenance mode on a Page Layout by typing in the following URL.

http://<server>/_catalogs/masterpage/<page layout name>.aspx?contents=1

 

Once on this page, I was able to successfully remove the ErrorWebPart from the template/page layout and could create new Pages from my Page Layout.

Nothing too exciting but thought it was worth noting.

Eli

Full stack trace:
No parameterless constructor defined for this object. at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck)

at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache)

at System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache)

at System.Activator.CreateInstance(Type type, Boolean nonPublic)

at System.Activator.CreateInstance(Type type)

at Microsoft.SharePoint.WebPartPages.SPWebPartSerializer.get_DefaultControl()

at Microsoft.SharePoint.WebPartPages.BinaryWebPartSerializer.Serialize(PersonalizationScope scope)

at Microsoft.SharePoint.WebPartPages.BinaryWebPartSerializer.get_Links()

at Microsoft.SharePoint.WebPartPages.SPWebPartManager.AddWebPartToStore(WebPart webPart, Int32 viewId, String viewGuid)

at Microsoft.SharePoint.WebPartPages.SPWebPartManager.AddWebPartInternal(SPSupersetWebPart superset, Boolean throwIfLocked)

at Microsoft.SharePoint.WebPartPages.SPLimitedWebPartManager.AddWebPartInternal(WebPart webPart, String zoneId, Int32 zoneIndex, Boolean throwIfLocked)

at Microsoft.SharePoint.WebPartPages.SPLimitedWebPartManager.AddWebPart(WebPart webPart, String zoneId, Int32 zoneIndex)

at Microsoft.SharePoint.Publishing.PublishingPage.CopyAllWebParts(String destinationPageUrlServerRelative, SPWeb destinationPageWeb, String sourcePageUrlServerRelative, SPWeb sourcePageWeb, Boolean shouldOverwriteDestinationWebParts)

at Microsoft.SharePoint.Publishing.PublishingPageCollection.<>c__DisplayClass5.<Add>b__0()

at Microsoft.Office.Server.Diagnostics.FirstChanceHandler.ExceptionFilter(Boolean fRethrowException, TryBlock tryBlock, FilterBlock filter, CatchBlock catchBlock, FinallyBlock finallyBlock)

at Microsoft.Office.Server.Diagnostics.ULS.SendWatsonOnExceptionTag(ULSTagID tagID, ULSCat categoryID, String output, Boolean fRethrowException, TryBlock tryBlock, CatchBlock catchBlock, FinallyBlock finallyBlock)

at Microsoft.SharePoint.Publishing.PublishingPageCollection.Add(String name, PageLayout layout)

at Microsoft.SharePoint.Publishing.Internal.CodeBehind.CreatePagePage.NewPageItemSave(String pageName, PageLayout pageLayout)

at Microsoft.SharePoint.Publishing.Internal.CodeBehind.CreatePagePage.CreateStandardPage(String pageName)

at Microsoft.SharePoint.Publishing.Internal.CodeBehind.CreatePagePage.ButtonCreatePage_Click(Object sender, EventArgs e)

at System.Web.UI.WebControls.Button.OnClick(EventArgs e)

at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)

at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)

at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)

at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)

at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

MOSS 2007 – SP2 / April CU Publishing Bug

July 28th, 2009 by undercoverlaptop

Overview of Bug

When editing a Content Editor Web Part Rich Text on a publishing page that is based off an page layout that contains User fields / people picker, such as the Contact field,  after saving the Rich Text changes the page refreshes and all of the user fields are "messed" up.   

Steps to reproduce

·         Ensure environment is April CU.  (We are not sure at this point if it is a bug introduced in SP2 or April CU since we did both upgrades at the same time.  April CU is version 12.0.0.6504
     
o    Central Admin –> Operations –> Servers in farm  
·         To keep it clean, I created a new Web Application to test this on.
·         I also created a new site collection based on the collaboration (Publishing tab) template.
·         Add a User / Person field control to the home page
     
o    Open up the new site collection with SharePoint Designer 2007
   o    Open the DefaultLayout.aspx page layout (which is the one used for the home page).  Check out if required. ( _catalogs/masterpage/defaultlayout.aspx )
   o    From the Toolbox, select SharePoint Controls –> Page fields 
   o    Then drag and drop the Contact control to somewhere on the page layout 
   o    Save and Publish / Approve page layout
·         Close SharePoint Designer 2007 and open the site collection home page
·         Edit the page and fill in a Contact
·         Save the page and check it in.
·         Edit the page again and add a Content Editor Web Part to one of the zones. 
·         Click the Open the Tool part link to get the web part editor panel
·         Click the Rich Text Editor button and add some simple text.
·         Click Ok to save and close the popup for the rich text editor
·         And VOLIA!

Next steps…

We'll be opening a ticket with Microsoft on this to see if they have heard of this (and maybe just maybe have a hotfix for it already).  We also applied June CU update and that did NOT fix the issue.

 

I wanted to get this out there to see if anybody else have had a similar issue and if anybody besides me and 4 different environments can reproduce the issue in their environment.

 

Thanks!

How to get Central Admin Link from API

March 26th, 2009 by undercoverlaptop

There are some applications that I use that reference lists in Central Administration and I needed a way to do a dynamic lookup of the URL for Central Administration. Here is the code that will return the URL…

public static string GetCentralAdminUrl()
{
   
// Grab the SPWebService for the administration site
   
SPWebService service = SPFarm.Local.Services.GetValue<SPWebService>("WSS_Administration");
   
if (service != null)
   
{
      
// Grabs the actual web application and reports the URL 
       
SPAdministrationWebApplication application = service.WebApplications.GetValue<SPAdministrationWebApplication>();
      
if (application != null)
      
{
           
return application.GetResponseUri(SPUrlZone.Default).ToString();
      

   
}
  
return null;
}

Hope it helps others so that they aren't hardcoding this link in their application.

Eli

Using the SPChangeQuery to detect Group Membership Changes

March 17th, 2009 by undercoverlaptop

I don't know how many people use the SPChangeQuery API but I find it to be extremely useful for a number of different options. You can use it to track sites/webs that are created, lists that are created and a number of other things. One thing that I thought was interesting was that someone wanted to monitor when a SharePoint group membership changed. As it turns out, you can use the SPChangeQuery to do this too. Check out the code sample.

// Connect to the Site collection you wish to monitor

using (SPSite site = new SPSite(http://localhost))
{

In this sample, I only want to get the last 15 minutes worth of changes from one particular site collection. I can scope it to a content database, web or list if I wanted to. Notice that you want to make sure that you cast your DateTime to UniversalTime otherwise if you are like me, living in EST, the change logs are 5 hours ahead which messes up the time token a little bit.

SPChangeToken myToken = new SPChangeToken(SPChangeCollection.CollectionScope.Site, site.ID, DateTime.Now.AddMinutes(-15).ToUniversalTime());

To avoid returning too much data, it is better to select what type of changes you want returned. I chose to only get changes made to the Group and it's membership. This way, I am not wasting time looping through changes such as list creation that I don't care about.

SPChangeQuery oQuery = new SPChangeQuery(false, false);
oQuery.ChangeTokenStart = myToken;
oQuery.Group = true;
oQuery.GroupMembershipDelete = true;
oQuery.GroupMembershipAdd = true;

Now it's time to get the data. Grab the changes from the site collection with your query and then begin looping through each SPChange object.

SPChangeCollection changes = site.GetChanges(oQuery);
foreach (SPChange change in changes)
{
  
if (change.GetType() == typeof(SPChangeGroup))
  
{
     
if (change.ChangeType == SPChangeType.MemberAdd || change.ChangeType == SPChangeType.MemberDelete)
     
{

 I cast it to an SPChangeGroup now so that I can get the additional metadata of userid and the group id.

SPChangeGroup cGroup = change as SPChangeGroup;
using (SPWeb web = site.OpenWeb())
{

Be careful here, I'm not testing to make sure the user still exists in the AllUser list or that the group still exists.

SPUser changedUser = web.AllUsers[cGroup.UserId];
SPGroup changedGroup = web.Groups[cGroup.Id];

 Last but not least, do whatever you want to do for membership deletion (email?) and membership addition.

if (change.ChangeType == SPChangeType.MemberDelete)
{
  
Console.WriteLine("{0} deleted from {1}", changedUser.Name, changedGroup.Name);
}
else if (change.ChangeType == SPChangeType.MemberAdd)
{
  
Console.WriteLine("{0} addded to {1}", changedUser.Name, changedGroup.Name);
} } } } } }

I hope this code sample helps.
Eli

Custom SharePoint Applications Logging Framework

March 12th, 2009 by undercoverlaptop

One of the things that I could never quite figure out about the SharePoint API is that they expose just about everything under the sun but when it comes to using their diagnostics / logging framework, it's all hands off. Granted, if you have the MOSS version, you can use PortalLog.LogString() method to write entries to the SharePoint ULS but for me that wasn't good enough. I wanted more control, control similar to what SharePoint does with their applications. Basically, I wanted the ability to set thresholds for my own diagnostics categories so that I could send anything that I wanted to the logs and depending on the threshold (verbose vs. unexpected) the system would determine whether to write it to the ULS and/or Windows Event Viewer.

Interesting enough, there isn't much information out there on how to do this so I had to start from scratch with the help of this article and Reflector. After much research, I think I am getting closer (if not almost done) to providing a way to log to SharePoint logs (and as an added bonus to the Event Viewer).

At a high level, there are four different aspects:

  1. DiagnosticsManager - In charge of performing the following:
  • Adding new Categories to the Diagnostics Logging page (Operations in Central Admin)
  • Controlling the thresholds (Event Severity & Trace Severity) for the new categories
  • Returning the values of the thresholds (severity levels) for the requested category — used on the Diagnostics Logging page and when your application needs to know whether to log it or not.
  1. DiagnosticsLevel - Basically just a data structure class to hold information about the category defined above such as Category Name, Id, Event Severity and Trace Severity
  2. TraceProvider – This is the basically the class that you create when you following the MSDN article mentioned above (http://msdn.microsoft.com/en-us/library/aa979522.aspx).
  3. Logging (static class) – Static methods that you, the developer, would be calling when you want to log to the SharePoint ULS or Event Viewer. In this class, we check to make sure that the WriteEntry request that you want to log falls within the threshold of the category that you define. Example would be something like this…

       SPLogger.RegisterApplication(LogCategory.MyCategory, "My SharePoint App", "Provosioning new Site", 1091); 

       SPLogger.WriteEntry(TraceSeverity.Verbose, "Stupid error message goes here");
       SPLogger.WriteEntry(TraceSeverity.Unexpected, EventSeverity.Error, "Unexpected");  

       SPLogger.UnRegisterApplication();

     Sample output: 
    
    03/12/2009 17:53:22.11     My SharePoint App (0×0CC8)     0×0B10    My Category     Provosioning new Site     1091    Verbose     Stupid error message goes here 
                 03/12/2009 17:53:22.11     My SharePoint App (0×0CC8)     0×0B10    My Category     Provosioning new Site     1091    Unexpected    Unexpected error        

This post is completely a high level overview because there isn't much sense going into details if nobody, aside from this insanely SharePoint obsessed developer, thinks it is useful :) If you want more details, leave a comment and I'll follow up with additional posts.

UPDATE: I posted the wrong link for the MSDN article.  AuditEntries are quite the same but I've my share of them too!

Eli

 

Install directories are imporant for Project Server 2007 and MOSS 2007

March 4th, 2009 by undercoverlaptop

I was recently working at a clients that had begun installing (on their own) Project Server 2007 into their MOSS environment.  However they were having all sorts of issues provisioning the PWA site.  Once we finally managed to get PWA provisioned, we began receiving an error that the language could not be determine.  This was Project's strange way of telling us that it can't find the Project Server web services.  As it turns out, the PSI web services files (which are suppose to be part of the Office Server Web Services web application), were missing.  After researching the properties in IIS, I realized that they installed MOSS onto the D:Project Fileslah blah blah instead of the default install location but when they installed Project Server, they used the default location (C:Program Files).  After copying the files for the PSI web services, (yeah yeah…probably should have reinstalled), the error message went away and FINALLY Project Server was up and running. 

On a side note, this also caused the databases from not being provisioning because the SQL scripts that it uses couldn't be found on the D: drive.

Go figures….lol.  Hopefully this will help some others from pulling their hairs out.

Eli

Some of the errors we were getting…

Failed to get language information for Project Server (Event ID 6058) — Event Log
System.IO.FileNotFoundException: PWA site not found
System.Net.WebExeption: the request failed with HTTP status 404: Not found at at Microsoft.Office.Project.Server.PSIAuth.Authentication.GetUserByName
Failed to provision database ProjectServer_Published as Published because directory D:Program filesMIcrosoft Office Servers12.0sqlproject servercore don't exist

 

Using SPDisposeCheck in Visual Studio

February 20th, 2009 by undercoverlaptop

One of the things that I like to use in Visual Studio 05 & 08 is the external tools.  After the much anticipated release of the SPDisposeCheck from Microsoft via codeplex (http://blogs.msdn.com/sharepoint/archive/2009/01/29/spdisposecheck-released.aspx), I thought…this would make a pretty cool External Tool.  Here is how I set it up…

1 )  In Visual Studio, select Tools –> External Tools
2)  Click Add and fill out the required fields…here is what I put

Title:  SPDispose Check
Command: C:Program FilesMicrosoftSharePoint Dispose CheckSPDisposeCheck.exe  (Path to executable)
Arguements: $(TargetName)$(TargetExt)                      (Note: I don't believe you can copy and paste this…you have to select them from the side button)
Initial Directory: $(TargetDir)
Use Output Window: Checked

When running it on my compiled DLL, here is what I got to my Output window.    Looks like it works pretty good…now to go see what it is complaining about :)

Note: This tool may report errors which are not actually memory leaks, otherwise known as false positives.
Further investigation should be done to identify and correct real errors.
It is designed to assist developers in making sure their code adheres to best practices for memory allocation when using SharePoint APIs.
Please see the following for more information:
http://blogs.msdn.com/rogerla/
http://msdn2.microsoft.com/en-us/library/aa973248.aspx
http://msdn2.microsoft.com/en-us/library/bb687949.aspx
———————————————————-
ID: SPDisposeCheckID_160
Module: Praxair.SharePoint.TemplateCustomizations.dll
Method: Praxair.SharePoint.TemplateCustomizations.Framework.PraxairProvisioner.Provision(Microsoft.SharePoint.SPWeb,System.String)
Statement: manager := web.{Microsoft.SharePoint.SPWeb}GetLimitedWebPartManager("default.aspx", 1)
Source: C:NetprojectsTeamEli.BlahBlahBlahTeamEli.BlahBlahBlahFrameworkProvisioner.cs
Line: 204
Notes: Dispose/Close was not called on SPLimitedWebPartManager.Web
More Information: http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_160
———————————————————-
Total Found: 1
———————————————————-

 

Modules Checked: 1
———————————————————-
TeamEli.BlahBlahBlah.dll
———————————————————-

Modules Ignored: 0
———————————————————-
———————————————————-

Methods Ignored: 0
———————————————————-

 

 

Record Center / Information Management Policy Jobs Not Running

October 13th, 2008 by undercoverlaptop

Interesting enough, we noticed after installing “something” (it could have been Project Server, Service Pack 1 or even the Infrastructure Update) that none of the time jobs managed by the PolicyConfig service were running.   If fact, they were all list as have never run, which I knew is a lie since they used to work at some point in time.  These jobs include:

Expiration Policy
Hold Processing and Reporting
Information Management Policy
Records Center Processing

In trying to troubleshoot this issue, I was messing around with one of the stsadm commands that can be used to set the when these four polices run.  However, when I tried to run the following command:

Stsadm -o setpolicyschedule -schedule “daily at 23:50:00″

 I would get an error saying “The Information Management Policy feature is not active.”  After a little bit more research, I found out that the “feature” that it is complaining about is the RecordsManagment feature.  Granted, this feature is scope at the Farm level and thereby is automatically activate, I took the liberty and ran

 stsadm -o activatefeature -name RecordsManagement -force. 

After running the re-activate command, I was then able to run the setpolicyschedule command (which I didn't need to do to resolve the issue) and volia my Information Management Policy's timer jobs are running again!

 

Use Powershell to get a new GUID

October 8th, 2008 by undercoverlaptop

In SharePoint development, you are always in need of generating a unique id (aka GUID) for your features and solutions.  While most developers have a GUID generator setup in Visual Studio, here is a quick alternative if you don't want to open Visual Studio but have Powershell open.

[System.Guid]::NewGuid().ToString()

 And volia…you have a new GUID that you can use in your application.

Eli

 

TeamEli's first CodePlex Project — GUI to Add Solutions to SharePoint Solution Store

October 8th, 2008 by undercoverlaptop

Well, I finally took the time to sit down and put together a CodePlex project for some of the application pages (ok…only one so far…) that I am building for SharePoint admins.  So far, I have an application page that allows SharePoint admins to upload SharePoint solutions into the solution store.  This gets rid of the need to have to log into the server to run that one pesty stsadm command (addsolution).  I am not sure if anybody will find this useful but I figured it would be a nice start for my presence on CodePlex.

TeamEli SharePoint (2007) Tools

 As far as the application goes, it's fairly straight forward.  A custom application page that resides in the ADMIN folder with a custom action on the operations page right underneath the Solutions Management link.  Turns out it is pretty easy to add new solution files to the store.  First, I have to save a copy of the file locally so that the API can access the file then I check to see if the solution already exists.  If it does, it upgrades the solution.  Otherwise, it just adds the solution to the store.

// Saves file to local system so that sharepoint can upload it
string path = "C:\Packages\" + upload_Solution.FileName;
upload_Solution.SaveAs(path);

// Gets current solution (if present)
SPSolution solution = SPFarm.Local.Solutions[upload_Solution.FileName];

if (solution == null)
{
     
// Adds new solution to farm
     
solution = SPFarm.Local.Solutions.Add(path);
}
else
{
    
if (solution.Deployed)
     {
          
// Upgrades the solution now.
          
solution.Upgrade(path, DateTime.Now);
     }
    
else
    
{
         
// Removes solution and re-adds it
         
solution.Delete();
          solution =
SPFarm.Local.Solutions.Add(path);
     }
}

Please feel free to give it awhirl and let me know what your thoughts are and if you have any problems.

Eli