Skip to main content

Blog de Alejandro Avila

Go Search
Home
  

 Documents

Paper Browser.8.5x11.Horizontal.pdfPaper Browser.8.5x11.HorizontalAlex Ávila
sketching.pdfsketchingAlex Ávila
website-stencil-template-a4.pdfwebsite-stencil-template-a4Alex Ávila
concept7_a4_sketching_paper_v01.pdfconcept7_a4_sketching_paper_v01Alex Ávila
mbti_sketching_concept7_a4.pdfmbti_sketching_concept7_a4Alex Ávila
PeopleSearchResultsCustomization.pptPeopleSearchResultsCustomizationAlex Ávila
Taxonomy-Sharepoint-2009.pptTaxonomy-Sharepoint-2009Alex Ávila
Understanding and Using Exceptions
 
(this is a really long post...only read it if you (a) don't know what try/catch is  OR (b) actually write catch(Exception ex)  or catch{ })

The first thing I look for when evaluating someone's code is a try/catch block. While it isn't a perfect indicator, exception handling is one of the few things that quickly speak about the quality of code. Within seconds you might discover that the code author doesn't have a clue what he or she is doing. It may be fun to point and laugh at, but poor exception handling can have a serious impact on the maintainability of a system. Proper exception handling isn't very difficult, technically there's nothing to it. It all comes down to grasping the fundamentals.  Too many developers consider exceptions dangerous to the health of a system. If you come from an exception-less language, you might be cursing Microsoft developers for ever having introduced them in the framework.

All exceptions in the .NET framework inherit from the base System.Exception class. This class exposes a handful of members you are likely familiar with, such as StackTrace and Message. Exceptions are raised by the framework, a library you are using or your own code when an exceptional situation occurs. While I don't often run into over zealous use of exceptions, it is important to understand that they are meant to be used for truly exceptional scenarios. For example, if a user's registration fails because the email is already in use, throwing an exception might not be appropriate. You'll often hear people say "only use exceptions in exceptional cases", as I just did. This is very sound advice when throwing your own exception, but what about catching and handling exceptions? Well the fundamental point to understand is the same, when an exception does get thrown, be aware that something truly exceptional happened.  That might sound a little bit obvious, but a common example will show just how poorly understood the point is:

try
  connection.Open()
  command.ExecuteNonQuery()
catch
  return false
end try


You might have seen, or even written, similar code before. In a previous blog post, I pointed out almost identical code in official Macromedia documentation. There's actually more than 1 problem in the above code, but let's focus on the catch block - the place the exception is supposed to get handled. Does anyone see the exception being handled? It isn't. Instead, we've been warned that something truly bad has happened, and swept it under the rug. This is known as exception swallowing, and it's a sure sign of someone who's afraid of and doesn't understand exceptions. If you truly understand that an exception is a sign of an exception situation, you'll never dare sweep it under the rug!

If you aren't supposed to swallow them, what's the game plan going to be? The first thing to realize is that much more often than not, there's nothing you'll actually be able to do with exceptions. If I was to guess as to why developers get hung up on exceptions, I'd have to say this is it. For many developers, having an exception bubble up through code, where it'll eventually cause the application to crash, seems unimaginable. For some reason, these same developers don't seem to be too worried about not being able to connect to their database - we'll just return false. The simple truth is that if you can't actually handle the exception, don't. We'll implement logging and friendly error messages much higher up in the code, where it can be globally reused and easily maintained. If the above code makes it to a production server, no error message will be displayed, no meaningful data will be recorded and it might take hours (or days) before you even know something's wrong.

Rethrownig exceptions
Does that mean that you should never catch exceptions? Not necessarily, but you need to be careful what you do in there. One of the few technical hangups developers have is how to rethrow a caught exception. Since it might not be obvious at first why you'd do that, let's look at an example. Pretend we've build code that allows user's to register. Our code will first enter the record into the database (assuming all business rules pass), and then send a confirmation email out that details how the account can be activated. If sending out the email fails, we'll want to remove the record from the database so that the user can try again with the same username/email (else he or she will get an error saying the username or email is already in use). With proper use of exceptions, this is a simple matter to accomplish:

try
{
  Emailer.SendNewUserActivation(this)
}
catch (SmtpException ex)
{
  this.Delete();
 
throw;
}


In the above code we haven't handle the exception, but we've done some important cleaning up. The code can't go in the finally clause because that's called on failure AND success (and we don't want to delete the record if everything was a success).  The real gem in the code is the throw statement. This keeps the exception on the stack, where it'll bubble upwards. The calling code won't know that we ever caught the exception and did a bit of internal house-cleaning - which is just what we want because we did nothing to handle the exception.

(in the comments below, Mark Kamoski has some alternative solutions to the code above (along with some concerns) that I think are worthwhile, so scroll down and find his post!)

There are two variations to the code above. Instead of simply using throw; we could actually use throw ex;. The difference between the two, though subtle, it quite important to understand. When you use throw ex; you'll modify the call stack and make it look like your code was the source of the exception. You are effectively throwing away useful debugging information. As I've said before, when you simply throw; it's as though you didn't do anything at all! We'll talk more about throwing your own exceptions in a later post, but if you want to actually be involved in the exception bubbling chain, it's generally better to throw a new exception and specified the caught exception as the inner exception, such as:

throw new SomeTypeOfException("User Activation send failed", ex);

Cleaning up after yourself
If you follow my advice (and I'll give you a much better source than just my own word soon), you'll end up with very few Try/Catch statements. Instead what you should be using are Try/Finally statements, or the using statement.  While you might not be able to handle an exception, you can certainly clean up after yourself. Most people know this, but finally happens whether an exception is raised or not, and is pretty much guaranteed to happen - so you can return in your try block and rest easy knowing your finally cleaned up your resources. Here's an example:

dim connection as new SqlConnection(GET_CONNECTION_STRING_FROM_CONFIG)
dim command as new SqlCommand(connection)
'...set stuff up
try
  connection.Open()
  'might wanna check for DbNull or something
  return cint(command.ExecuteScalar)
finally
 connection.Dipose()
 command.Dispose()
end try


If you instantiate your code inside the try, make sure to check for nothing before disposing:

dim connection as SqlConnection
dim command as SqlCommand
try
  connection = new SqlConnection(GET_CONNECTION_STRING_FROM_CONFIG)
  command = new SqlCommand(conection)
  '...set stuff up
  connection.Open()
  'might wanna check for DbNull or something
  return cint(command.ExecuteScalar)
finally
 if (not connection is nothing) then
    connection.Dipose()
 end if
 if
(not command is nothing) then
    command.Dispose()
 end if
end try

 
The above code is a little messy, which is exactly why C# and VB.NET (as of 2005) support the using keyword:

using (SqlConnection connection = new SqlConnection(...))
{
  using (SqlCommand command = new SqlCommand(...))
  {
    //..set stuff up
    connection.Open();
    return Int32.Parse(command.ExecuteScalar);
  }
}


I've heard some people say they dislike nested using statements, but if you compare the two examples, I think it's much cleaner, readable and less error prone.

More on actually catching exceptions
Now there are some times when you'll be able to handle an exception. Everyone knows that you always catch specific exceptions first and work your way towards the base exceptions. You should also, never-ever catch System.Exception. Say we wrote code that took a query string value (or any string for that matter) and tried to turn it into an integer. If it fails, we want to default to a given value. You might write something like:

public static int ParseInt(string value, int defaultValue)
{
 try
 {
  return Int32.Parse(stringValue);
 }
 catch(Exception ex)
 {
  return defaultValue;
 }
}


That's wrong. What happens if Int32.Parse threw a ThreadAbortException or an OutOfMemoryException, does returning a defaultValue handle those exceptions? No. Instead, you need to catch only the specific exceptions you are handling:

try
{
  return Int32.Parse(stringValue);
}
catch (FormatException ex)
{
 return defaultValue;
}
catch (InvalidCastException ex)
{
 return defaultValue;
}
catch (OverflowException ex)
{
 return defaultValue;
}


Of course, that can be a serious pain to write and maintain. The solution is to apply what we learnt earlier about rethrowing caught exceptions:

try
{
 return Int32.Parse(stringValue);
}
catch (Exception ex)
{
  if (!(ex is FormatException) && !(ex is InvalidCastException) && !(ex is OverflowException))
  {
    throw;
  }
  return defaultValue;
}

While it's true I said that you should never catch Exception, notice that it's being rethrown (using throw;) if it isn't the expected type. This works just as well in VB.NET, or you can even use VB.NET's when clause.

Global Error Handling
If you've made it this far, you might be getting a little panicked. Since we aren't catching exceptions left and right, they'll bubble until they crash the system. Well that's where global exception handling comes in. It lets us write, in a centralized (i.e., easy to change) way, any exception logging we want and how to display the error in a friendly manner. Now I'm getting a little tired of typing, but here's the httpModule I use to get the job done (notice it relies on log4net to do any logging). If you aren't familiar with httpModules, and you don't want to bother learning, you can take the code from application_error and stick it in your global.asax's application_error.

using System;
using System.Web;
using log4net;

namespace Fuel.Web
{
   public class ErrorModule : IHttpModule
   {
      #region Fields and Properties
      private static readonly ILog logger = LogManager.GetLogger(typeof(ErrorModule));
      #endregion

      #region IHttpModule Members      
      public void Init(HttpApplication application)
      {
         application.Error += new EventHandler(application_Error);  
      }      
      public void Dispose() { }
      #endregion

      public void application_Error(object sender, EventArgs e)
      {
         HttpContext ctx = HttpContext.Current;
         //get the inner most exception
         Exception exception;
         for (exception = ctx.Server.GetLastError(); exception.InnerException != null; exception = exception.InnerException) { }
         if (exception is HttpException && ((HttpException)exception).ErrorCode == 404)
         {
            logger.Warn("A 404 occurred", exception);
         }
         else
         {
            logger.Error("ErrorModule caught an unhandled exception", exception);
         }
         ctx.Server.ClearError();
         //if you want, you  can simply redirect to a generic "oops, an error occurred page" ala:
         //this is what I recommend until you get into creating your own exceptions
         //Response.Redirect("error.asx");

         
      }
   }
}


What if you disagree with me?
You might disagree with what I've said. You might even point to this MSDN reference that supposedly tells you how to handle exception: http://msdn2.microsoft.com/en-us/library/24395wz3.aspx.  In it you'll find very different advice, namely:

"It is preferable to use Try/Catch blocks around any code that is subject to errors rather than rely on a global error handler."

I'll counter that crap (and i am trying to get it corrected, because it IS flat out wrong), with a quote from Anders Hejlberg (you know, the lead architect for C#, one of few Microsoft distinguished engineers, the inventor of TurboPascal and a lot more):

"No, because in a lot of cases, people don't care. They're not going to handle any of these exceptions. There's a bottom level exception handler around their message loop. That handler is just going to bring up a dialog that says what went wrong and continue. The programmers protect their code by writing try finally's everywhere, so they'll back out correctly if an exception occurs, but they're not actually interested in handling the exceptions.

The throws clause, at least the way it's implemented in Java, doesn't necessarily force you to handle the exceptions, but if you don't handle them, it forces you to acknowledge precisely which exceptions might pass through. It requires you to either catch declared exceptions or put them in your own throws clause. To work around this requirement, people do ridiculous things. For example, they decorate every method with, "throws Exception." That just completely defeats the feature, and you just made the programmer write more gobbledy gunk. That doesn't help anybody.

It is funny how people think that the important thing about exceptions is handling them. That is not the important thing about exceptions. In a well-written application there's a ratio of ten to one, in my opinion, of try finally to try catch. Or in C#, using statements, which are like try finally.

In the finally, you protect yourself against the exceptions, but you don't actually handle them. Error handling you put somewhere else. Surely in any kind of event-driven application like any kind of modern UI, you typically put an exception handler around your main message pump, and you just handle exceptions as they fall out that way. But you make sure you protect yourself all the way out by deallocating any resources you've grabbed, and so forth. You clean up after yourself, so you're always in a consistent state. You don't want a program where in 100 different places you handle exceptions and pop up error dialogs. What if you want to change the way you put up that dialog box? That's just terrible. The exception handling should be centralized, and you should just protect yourself as the exceptions propagate out to the handle."

(you can read the entire interview here, very good read, especially if you come from a Java backgorund)

Make sure to read that and understand that well, because it's all amazing advice and the real foundation of what you need to know with respect to exception handling.

In Closing:
Here are the key points:
- Don't catch exceptions unless you can actually handle them
- Do know how to rethrow exceptions properly
- Do use using or try/finally often
- Don't swallow exceptions
- Do use a global handler to help you log and display a friendly error message

I did want to talk about creating your own exceptions, but I think I'll save that for another post.
 
SharePoint Server 2010 Preliminary System Requirements

source: http://blogs.msdn.com/sharepoint/archive/2009/05/07/announcing-sharepoint-server-2010-preliminary-system-requirements.aspx

We’ve heard loud and clear that you want system requirements information as early as possible to assist in your budgeting and planning, so today we’re happy to announce (and confirm) some preliminary system requirements for SharePoint Server 2010:

  1. SharePoint Server 2010 will be 64-bit only.
  2. SharePoint Server 2010 will require 64-bit Windows Server 2008 or 64-bit Windows Server 2008 R2.
  3. SharePoint Server 2010 will require 64-bit SQL Server 2008 or 64-bit SQL Server 2005.

In addition to the requirements listed above we also wanted to share with you some preliminary detail about SharePoint Server 2010 browser compatibility. 

To ensure the best possible experience across multiple browsers we’re focusing our SharePoint 2010 engineering efforts on targeting standards based browsers (XHTML 1.0 compliant) including Internet Explorer 7, Internet Explorer 8 and Firefox 3.x. running on Windows Operating Systems.  In addition we’re planning on an increased level of compatibility with Firefox 3.x and Safari 3.x on non-Windows Operating Systems.  Due to this focus Internet Explorer 6 will not be a supported browser for SharePoint Server 2010.

So, what can you do today to get into the best shape for SharePoint Server 2010?

  1. Start by ensuring new hardware is 64-bit.  Deploying 64-bit is our current best practice recommendation for SharePoint 2007.
  2. Deploy Service Pack 2 and take a good look at the SharePoint 2010 Upgrade Checker that’s shipped as part of the update.  The Upgrade Checker will scan your SharePoint Server 2007 deployment for many issues that could affect a future upgrade to SharePoint 2010.
  3. Get to know Windows Server 2008 with SharePoint 2007, this post is a great starting point.
  4. Consider your desktop browser strategy if you have large population of Internet Explorer 6 users.
  5. Continue to follow the Best Practices guidance for SharePoint Server 2007.
  6. Keep an eye on this blog for updates and more details in the coming months.

Below are a few common Q&A’s (which we’ll add to as required)

 

Q: What about Internet Explorer 6 and SharePoint 2010 publishing sites?
A: The Web Content Management features built into SharePoint 2010 will provide a deep level of control over the markup and styling of the reader experience.  These features will enable customers to design pages that are compatible with additional browsers for viewing content, including Internet Explorer 6.  A standards based browser such as Internet Explorer 7, Internet Explorer 8 or Firefox 3.x will be required to author content.

Q: Is Internet Explorer 6 officially supported by Microsoft?
A: Official Microsoft Product Support for Internet Explorer 6 follows the lifecycle of the Operating System with which it was shipped.  In order for customers to receive product support through the Mainstream Support and Extended Support phases, they need to have installed a supported Service Pack.  For example, customers who are using Windows XP must transition to Service Pack 3 by July, 2010 and are eligible to receive support for Internet Explorer 6 until April, 2014.

You can find additional information on Microsoft’s Support Lifecycle Policy including specific dates, product information and support offerings here: http://support.microsoft.com/gp/lifepolicy.

Q: Why are you only supporting the 64-bit versions of SQL Server 2005 or 2008 for SharePoint Server 2010?
A: This decision was based on our current test data for SharePoint Server 2010 and real world experience from customers running SharePoint Server 2007 with 32-bit SQL Server.  SharePoint performance and scalability can benefit significantly from 64-bit SQL Server and the throughput increases are significant enough for us to make the difficult decision to only support SharePoint Server 2010 on 64-bit SQL Server 2005 or 2008.  It has been our strong recommendation for some time that SharePoint Server 2007 customers take advantage of 64-bit SQL Server due to the inherent performance and scale benefits it can provide.

Q: Where can I find more information on the advantages of 64-bit hardware and guidance on how to migrate SharePoint from 32-bit to 64-bit.
A: These two TechNet articles are a good starting point;

Advantages of 64-bit hardware and software (Office SharePoint Server 2007)

Migrate an existing server farm to a 64-bit environment (Office SharePoint Server 2007)

source: http://blogs.msdn.com/sharepoint/archive/2009/05/07/announcing-sharepoint-server-2010-preliminary-system-requirements.aspx

Sharepoint Debug Message Errors

source: http://vspug.com/janeleung/2008/08/21/debugging-sharepoint-webparts-tips-reminder/

Every once in a while, I am debugging a webpart on SharePoint and all of a sudden, the page broke. The error message on the page is "An unexpected error occurred" which tells me nothing other than the fact that it's an error.

To turn the not-at-all-helpful error message into a meaningful one (meaningful for the development environment), 2 easy changes in the web.config file:

<customErrors mode="Off" /><!– change the mode from “On” to “Off” –> 

 

<!– change the CallStack from “false” to “true”–><SafeMode MaxControls="200" CallStack="true" DirectFileDependencies="10" ..

source: http://vspug.com/janeleung/2008/08/21/debugging-sharepoint-webparts-tips-reminder/

ServerTemplate numbers for Sharepoint
100 Generic list
101 Document library
102 Survey
103 Links list
104 Announcements list
105 Contacts list
106 Events list
107 Tasks list
108 Discussion board
109 Picture library
110 Data sources
111 Site template gallery
112 User Information list
113 Web Part gallery
114 List template gallery
115 XML Form library
116 Master pages gallery
117 No-Code Workflows
118 Custom Workflow Process
119 Wiki Page library
120 Custom grid for a list
130 Data Connection library
140 Workflow History
150 Gantt Tasks list
200 Meeting Series list
201 Meeting Agenda list
202 Meeting Attendees list
204 Meeting Decisions list
207 Meeting Objectives list
210 Meeting text box
211 Meeting Things To Bring list
212 Meeting Workspace Pages list
300 Portal Sites list
301 Blog Posts list
302 Blog Comments list
303 Blog Categories list
850 Page Library
1100 Issue tracking
1200 Administrator tasks list
2002 Personal document library
2003 Private document library
Create a custom navigation for sharepoint
 

PortalSiteMapProvider Instances

In general, you shouldn't create new instances of PortalSiteMapProvider to be discarded after use in a single method. These objects contribute to a lot of memory use and are designed to be shared across a large number of requests. Any PortalSiteMapProvider instances declared in web.config can be accessed with:

PortalSiteMapProvider portalProvider = (PortalSiteMapProvider)SiteMap.Providers["<InstanceName>"];

MOSS declares a number of instances of PortalSiteMapProvider in web.config which are used for rendering navigation. For convenience, the PSMP class exposes a number of static properties which allows even easier access to these standard named instances. In addition, there is a similar static property defined for "WebSiteMapProvider" which doesn't correspond to a definition in web.config, but is a useful instance of PortalSIteMapProvider for caching purposes as it returns only webs. By default, an instance of PSMP returns webs, Publishing pages, headings and authored links - the 4 different types of items that show up in navigation. The following properties are set on this provider at initialization time in order to remove (possibly) unwanted items:

// do not limit the number of children a particular node may store
webSiteMapProvider.DynamicChildLimit = 0;
// do not include pages in results
webSiteMapProvider.IncludePages = IncludeOption.Never;
// do not include authored links in results
webSiteMapProvider.IncludeAuthoredLinks = false;
// do not include headings but return nodes beneath headings
webSiteMapProvider.FlattenHeadings = true;


See http://msdn2.microsoft.com/en-us/library/microsoft.sharepoint.publishing.navigation.portalsitemapprovider_members.aspx for the full list of configurable properties for the provider. Most of these properties affect the collection of nodes returned by the GetChildNodes method which I'll touch on in just a minute. Depending on your scenario, it may make sense to define your own static instance of PortalSiteMapProvider with a configuration that suits your needs.

PortalSiteMapProvider.FindSiteMapNode

This method allows fast and easy access to webs by URL:

PortalSiteMapProvider portalProvider = PortalSiteMapProvider.WebSiteMapProvider;
PortalSiteMapNode webNode = ((PortalSiteMapNode)portalProvider.FindSiteMapNode("/site/web"));
System.Console.WriteLine(webNode.Title);

You can also access Publishing pages in a similar fashion, using a different provider which doesn't exclude pages:

PortalSiteMapProvider portalProvider = PortalSiteMapProvider.CurrentNavSiteMapProviderNoEncode;
PortalSiteMapNode pageNode = ((PortalSiteMapNode)portalProvider.FindSiteMapNode("/site/web/Pages/Page1.aspx"));
System.Console.WriteLine(pageNode.Title);

Be aware though, you cannot fetch the default page of a web, as you will be returned a node representing the web itself. This quirk has to do with providing the right set of navigation links for the navigation menus - after all, the PSMP is first and foremost a navigation site map provider. I discuss a different technique which does allow you to fetch the default page, a little later.

Add multiline field to ECQWP

source: http://www.heathersolomon.com/blog/articles/CustomItemStyle.aspx

First, hands down this is a fantastic blog post to read on the subject: Configuring and Customizing the Content Query Web Part on the ECM Blog.   That post is what I followed to create custom Item Styles.  This article is just to help fill in the blanks on how to use this process for your own site.

I am going to breeze through some of the steps that are documented on the ECM blog, and go into others in more detail that are not documented in that post. 

Add a CQWP To The Site

  1. Add a Content Query Web Part to a page in the site. By default the CQWP will display all of the pages in the site.
  2. Now choose to Modify the Shared Web Part and in the Web Part Tool Pane, expand Query and change the Source settings to the site or list where you want to query the data from. 

    Query settings in the Tool Pane

  3. Optionally update other settings to further refine the data view, such as Content Type and Filters. Select Apply.
  4. For more details, look and Steps 1 and 2 in the Configuring and Customizing the Content Query Web Part post.

Create the Custom Item Style

Now we have a rather boring view of some data. We use Item Styles to jazz up the formatting and selectively show various content, such as Title, Description and Body.  There are already several Item Styles available out-of-the-box, but in my opinion, they have limited use. Go ahead and play around with what is available, there maybe something there that is perfect for your needs and it helps you to see what you can do with an Item Style.  In the Tool Pane, expand Presentation and experiment with the drop down options under Styles. Select Apply to see the changes.

Before we style any content, we need to have the web part pull in the content we want to display. Some content is already pulled in by default, such as Title.  For anything else that is not pulled by default, we need to tell the web part to get those fields. But how do we know which fields are already being pulled in?  It is a bit of a chicken and the egg ordeal, so here are my suggested steps for working all of this information out:

Heads up!  Here is where we deviate from the Configuring and Customizing the Content Query Web Part post.

  1. Open the site in SharePoint Designer (SPD). Navigate to Style Library, then XSL Style Sheets. Open ITEMSTYLE.XSL.  Now doing this will customize (uhghost) the file! But we can always reset this back to the Site Definition and restore it to it's original state.  Be sure to check out the file via SPD or the Site Content and Structure screen in the site.
  2. Take a minute to look at the file.  Every time you see "<xsl:template..." that is the start of a new Item Style.  There is one for each of the out-of-the-box Item Styles that show up in the Styles drop down in the Web Part Tool Pane.  For every custom Item Style that is needed, a new xsl:template block will have to be created.
  3. Scroll down to the bottom of the file. Copy the last xsl:template code block and paste it above the closing xsl:stylesheet tag.
  4. Change the name and match properties in the Template tag to a unique name of your choice:

    <xsl:template name="MyCustomStyle" match="Row[@Style='MyCustomStyle']" mode="itemstyle">
  5. Next we will add a little snippet of code within the Template tags that will render the names of the fields that are being passed.  Note that this code will be temporary! We don't want to leave this in the finished Item Style.

    <xsl:template name="MyCustomStyle" match="Row[@Style='MyCustomStyle']" mode="itemstyle">
    <xsl:for-each select="@*">
        P:<xsl:value-of select="name()" />
    </xsl:for-each>
  6. Save the file.  Return to the site (in the browser) and refresh the page.  Open the Web Part Tool Pane for the CQWP and expand Presentation, then under Styles change the Item Style to the new custom style in the drop down.  Select Apply.
  7. The CQWP will now list out all of the fields that are being passed.

    CQWP Passed Fields

    After each P: is the internal column name for each field that is being passed.  These internal column names are what is referenced later in the code to display the data.  For example:

    <div class="description">
        <xsl:value-of select="@Description" />
    </div>


    Description is the internal column name that is being wrapped and styled with a DIV tag and is the content that will display on the page.  So we can look at the names displayed in the CQWP and see what data is already available for our use.  For example, in this particular case we have Title, Author, Publishing Rollup Image and Publishing Date (PubDate).

Find the Additional Data

Our first goal was to determine what content is already being pulled into the web part.  Now that we have done that, next we need to tell the web part to pull the other data we need. To do this we will need to get the internal column names for the necessary column(s) from the Content Type that is being used for the list.

  1. In the site, open Site Settings, then select Site Content Types.  Locate the Content Type that the list is using.  For example:
    • If you are querying a site and showing pages, look under Page Layout Content Types.
    • If you are querying a list, look under List Content Types.
  2. Select the Content Type name to view the Columns. Locate the column that needs to display in the custom item style. Locate the internal column name one of two ways:
    1. Way One: Click the column name.  In the Change Site Content Type Column screen, hover over the Edit site column in new window link and note the URL that appears in the Status Bar.  The internal column name appears after Field=. It also appears on the Site Content Type screen we just came from in the Status Bar, it is just inline with a lot of other characters. Often the string is too long in the Status Bar to display the Field property.

      Internal column name

    2. Way Two: Right click the link and select Properties.

      Content Type Columns

      The URL listed in the General tab has the info we need, just hidden below the viewable area.  Select the URL with your cursor, hit Ctrl + A to select the full URL, the copy and paste the URL into Notepad.

      Copy the URL

      In the pasted URL in Notepad, locate Field=.  The name that follows in the internal column name.

      Internal Column Name

Now that we have our internal column name, we can return to the instructions in the Configuring and Customizing the Content Query Web Part post and proceed with their Step 3.

Modify the CQWP to Include Additional Data

  1. In your site, in the CQWP, select Export from the web part's Edit menu. Save the .WEBPART file locally.
  2. Open the .WEBPART file in Notepad and search for "CommonViewFields". Replace the Property tag line of code with the code listed below, using your internal column name and the corresponding field type. It is very important that the field type listed is the correct type for the the data. If the field type is wrong, it won't break the site, but the Item Style won't display the content. Available values are:
    • Text
    • Note
    • Number
    • Currency
    • Integer
    • Boolean
    • DateTime
    • Threading
    • Lookup
    • Choice
    • URL
    • Counter
    • DisplayOnly (DisplayOnly field type has no storage of its own)


    • And I have either used or seen these used, but have not seen them documented anywhere:
    • RichHTML
    • Image

    Some field types are easy to figure out.  If we are calling a date, use DateTime. For Title use Text, for body content use RichHTML. String together multiple entries with a semicolon between each pair: Name, RichHTML; Name2, Text.

    <property name="CommonViewFields" type="string">InternalColumnNameGoesHere, FieldType</property>

    For example: <property name="CommonViewFields" type="string">Comments, Note</property>

    At the end of this article I cover how to find out the field type.

  3. Save the file and import it back into the site. (Add a Web Part - Import - select the .WEBPART file - Upload - Drag and drop the web part onto the page).

Now we have two CQWPs on the page.  We can remove the original one. We should also see the newly added internal column name(s) appear in the list of fields.  Yay!!  18 steps later and now we are ready to style!!  No, really, this process moves pretty fast.  Now it is time to return to the XSL file and start making things pretty.

Style the Data in the Item Style

  1. Return to SharePoint Designer and your custom template in ITEMSTYLE.XSL.
  2. For every internal column name that has been included in the web part and needs to display in the Item Style, add it to the template using the xsl:value tag:

    <xsl:value-of select="@InternalColumnNameGoesHere" />

    For example: <xsl:value-of select="@Comments" />

  3. Wrap HTML around the tag to format the data. 
    Please note!!
    When the page renders the CQWP, the site grabs the Item Style for each line of data.  So we can't add a table and expect that each line of data will be in a row.  Instead we get a full table for each line of data.  Keep this in mind as you style the HTML around the data.
  4. Save the file, go to the site and refresh the page.  The new styled content will appear.
  5. To remove markup tags, please refer to about the middle of Step 4 in the Configuring and Customizing the Content Query Web Part post.
  6. When done styling the Item Style, remove the code that lists the fields.
    <xsl:for-each select="@*">
        P:<xsl:value-of select="name()" />
    </xsl:for-each>

The Other Internal Column Names & Finding Field Types

If by some odd reason you were following along with this article and trying to do a CQWP Item Style on an events list, like I was, at the end of this you were probably scratching your head as to why no content would display on your site.  While writing this article I discovered that the internal column name listed in the Content Type isn't necessary the internal content name that should be used for Item Styles.  I am sure I will make some developer have a heart attack with my terminology or what have you, but after a lot of searching I tracked down the real internal column names in the SCHEMA.XML file for each feature (every list type is a Feature). Once I pulled the right internal column name in my .WEBPART file and in ITEMSTYLE.XSL, things worked like a charm.  Consequently, SCHEMA.XML also lists out the field types for each column.

  1. On the web server, open the SCHEMA.XML file for the Feature. The Features are located in the Feature directory:
    Local Drive:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\(Feature Name)
  2. Locate the SCHEMA.XML file.  It will be in one of the two subdirectories in the Feature.  Open the file in Notepad.
  3. Locate the FIELDS element.  Within Fields are all of the FIELD elements used in the Feature.  Each one lists the column Type (field type) and Name (internal column name).

    Schema file
  4. Use this column type and name in the .WEBPART file and in the ITEMSTYLE.XSL file.

To wrap up my commentary with the Events list, I changed "Comments" to "Description" and the CQWP successfully displayed the content in the CQWP

source: http://www.heathersolomon.com/blog/articles/CustomItemStyle.aspx

FullTextSqlQuery throwing exception – this site is not assigned to an indexer

source: http://grumpywookie.wordpress.com/2009/11/14/fulltextsqlquery-throwing-exception-this-site-is-not-assigned-to-an-indexer/

Following on from my presentation at SharePoint Saturday in Melbourne, I thought I’d relay a tip to those looking to code a webpart or such using FullTextSqlQuery.

During the development of my code, I was getting errors when running the following code :

FullTextSqlQuery fullTextSqlQuery = new FullTextSqlQuery(SPContext.Current.Site)
{
    ResultTypes = ResultType.RelevantResults, 
    QueryText = stringBuilder.ToString(),
    TrimDuplicates = true,
    EnableStemming = true,
    StartRow = 1,
    RowLimit = 200,
    TotalRowsExactMinimum = 300,
    IgnoreAllNoiseQuery = false,
};

//Return the search results to a ResultTableCollection
resultTableCollection = fullTextSqlQuery.Execute();

What was happening in the UI was a message stating :

Your search cannot be completed because this site is not assigned to an indexer. Contact your administrator for more information.

Took me a few DAYS of investigation to work a fix – as the code was compiling, and executing – just couldn’t connect to the Search Service within SharePoint.

And it turns out that my code was somehow causing a COM Exception within the WSS Search Service – and was listed in the Event Viewer also. 

I was having to go to Control Panel > Services – and re-start the “Windows SharePoint Search” service.

What’s going on !

Well – you may be aware that there’s a separate web service for both WSS and MOSS.  It follows that you can use the API to interact with either of these – and my code was incorrectly trying to use the WSS not MOSS class libraries.

The core issue was with my project references within Visual Studio

The key to my discovery was with this code :

ResultTypes = ResultType.RelevantResults, 

When I tried to add the option for “SpecialTermResults” (aka BestBets), I was getting a .NET error – saying ‘invalid member’ or something :

ResultTypes = ResultType.RelevantResults, ResultType.SpecialTermResults,  

But – this is within the SharePoint class library from MSDN.

It was then that I realised my FullTextSqlQuery class was referenced from :

  • using Microsoft.SharePoint.Search.Query   // WSS

– instead of

  • using Microsoft.Office.Server.Search.Query   // MOSS

It follows that the project file (DLL) references were wrong also. 

And yep – swapping them out fixed the problem !    *phew*

So – if you’re having this error – then check your solution/project references :

WSS Search

DLL : C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI\Microsoft.SharePoint.Search.dll

NameSpace : Microsoft.SharePoint.Search.Query

MOSS Search

DLL : C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI\Microsoft.Office.Server.Search.dll

NameSpace : Microsoft.Office.Server.Search.Query

Kinda obvious in the end :

  • If included as “SharePoint” only – it’s WSS
  • Need to have “Office Server” for MOSS

Wish I’d known all this earlier – it would have saved me a few stressful days !

source: http://grumpywookie.wordpress.com/2009/11/14/fulltextsqlquery-throwing-exception-this-site-is-not-assigned-to-an-indexer/

15 Ways to Tell Its Not Cloud Computing

source: http://www.redmonk.com/jgovernor/2008/03/13/15-ways-to-tell-its-not-cloud-computing/

If you peel back the label and its says “Grid” or “OGSA” underneath… its not a cloud.

If you need to send a 40 page requirements document to the vendor then… it is not cloud.

If you can’t buy it on your personal credit card… it is not a cloud

If they are trying to sell you hardware… its not a cloud.

If there is no API… its not a cloud.

If you need to rearchitect your systems for it… Its not a cloud.

If it takes more than ten minutes to provision… its not a cloud.

If you can’t deprovision in less than ten minutes… its not a cloud.

If you know where the machines are… its not a cloud.

If there is a consultant in the room… its not a cloud.

If you need to specify the number of machines you want upfront… its not a cloud.

If it only runs one operating system… its not a cloud.

If you can’t connect to it from your own machine… its not a cloud.

If you need to install software to use it… its not a cloud.

If you own all the hardware… its not a cloud.

If it takes 20 slides to explain…. its not a cloud

source: http://www.redmonk.com/jgovernor/2008/03/13/15-ways-to-tell-its-not-cloud-computing/

1 - 10 Next

 ‭(Hidden)‬ Admin Links