# Tuesday, November 01, 2011

Sharepoint Designer 2010 prompts even when installed

To give credit where credit is due - this came from http://social.technet.microsoft.com/Forums/en-US/sharepoint2010customization/thread/e437b1a9-688b-42ba-a32f-866d8d692187/

I had rebuilt my computer and even after installing Sharepoint Designer 2010 it would prompt me to download and install it whenever I selected "Edit in Sharepoint Designer". Even re-downloading and reinstalling did not help.

Luckily we have the web, and I located the discussion above. The issue is that I had disabled the "Sharepoint OpenDocuments Class" add-on.

First, select Manage Add-Ons from the Tools dropdown

Second Enable the "Sharepoint OpenDocuments Class" add-on

Voila! Problem fixed...

# Tuesday, October 04, 2011

Sharepoint 2010 - How to Filter a View by the User Viewing

First off, let me give credit where credit is due - I needed this solution and found it at http://decodesharepoint.blogspot.com/2010/02/filter-items-in-view-by-user-or-group.html, a site I will most assuredly go back to. I have added pictures, but the concept comes from there.

The question is how to setup a view that causes a list to filter the items dependent upon the user viewing it. The pain in this process is that you need to manually specify for each item who should view it. Nonetheless this can be an enormous time saver.

Here is how to do it:

  1. On the list that you want to filter, create a new Column which is of type "Person or Group", enable it to allow multiple selections (if you are going to have more than one person in the list) and select "People Only"




  2. Create a view




  3. In my case I have called the view "FilteredByUsers" (you can always rename it to include spaces later if you wish) and I have set it as the Default View (which is optional). What is critically important is that in the "Filtered" section of the View you specify that FilteredBy column (created in Step #1) "is equal to" [Me].



    [Me] is the short notation for the variable that refers to the person viewing (ah, hints of old VB...)

  4. Add (or modify) an Item to include the person who will be able to view it. In this case both myself and Odie will be able to view it in the FilteredByUser view....



The Result

Now you can switch between two views - the "All Items" which will display items regardless of who is in the "FilteredBy" column; and the "FillteredByUsersView" that will only display on those items in which the user has been included in the FilteredBy column.

 

# Wednesday, September 28, 2011

Cannot Assign Date to Sharepoint 2010 DateTimePicker

I was attempting to change the date on an Sp10 DateTimePicker control by code like this:

uxMySPDateTimePicker.SelectedDate = new DateTime(2011,10,10);

It did not work. As I stepped through it I noticed that it was 'assigned' but it was not persisted to the refresh. Luckily for me (and you) I stumbled across this thread fairly quickly -> http://www.eggheadcafe.com/microsoft/SharePoint-Windows-Services/31645560/problem-with-sharepoint-datetimecontrol.aspx

Basically you need to run the Clear method before you assign your date, like so ->

uxMySPDateTimePicker.Clear();
uxMySPDateTimePicker.SelectedDate = new DateTime(2011,10,10);

Hope that helps!

# Friday, September 09, 2011

Sharepoint 2010 - Control Event not Firing

This was a rather odd one. I was using sp10's DateTime Control. It is fairly nifty, although I would like a DateChanging event so that you could more easily roll it back if there was a problem.

Still I was using it to trigger an Ajax update of a Gridview. When I ran it initially the DateChanged event fired, but as I moved forward in coding it suddenly stopped.

After a lot of backtracking and investigation I discovered that it had to do with the fact that the bit of code that set the Gridview was running BEFORE the DateChanged method did. By doing this it confused it and prevented it from firing. A quick change and it works like a charm...

:)

# Thursday, August 18, 2011

Sharepoint 2010 - How do I find out the Internal Name of my List's Column?

I have mentioned this in another blog - (http://www.myfriedmind.com/techBlog/2011/07/25/Sharepoint2010HowBestToReferenceAColumnFieldFromAnSPListItem.aspx), but I thought I would pull it out since people appear to be searching specifically for this question. I cannot take credit for this - this was suggested by Mike Morton at MSoft after he noticed the way I was suggesting.

There are a number of ways that you can find out the information on a List's Column (also referred to as a Field). Unlike Sharepoint 2007 you cannot open up the database and take a look at the XML text stored there because it is no longer stored as XML text (admit it - you poked around in the database too even though they told you not to...).

You could access it through Webservices, or put a watch into code, but the most elegant solution is to take advantage of Visual Studio 2010's Server Explorer (from the View menu choice). Select the Sharepoint server you want, browse to the List, click on the Column and voila!

# Wednesday, August 17, 2011

Sharepoint 2010 - List Event Code not being triggered

There are undoubtedly a number of reasons why this might happen, but here are two quick ones to check, both can be found in the Elements.xml file

  1. Is the ListTemplateId correct?
  2. Is the Event registered in the Elements.xml

Is the ListTemplateId correct?

Different List types (such as Contacts vs Announcements vs Custom) have different ListTemplateIds. If you meant to target a Custom List type (id = 100) but clicked through too quickly when creating the program you got the Announcements List type (id = 104). The code will only trigger on the appropriate List type. Luckily the solution is simply to change the ListTemplateId in the Elements.xml file of your project.

A quick search got me the list from http://sharepoint-snippets.com/list-template-id-for-sharepoint-lists/. I replicate it below simply because blogs do disappear.

List template nameListTemplateID
NoListTemplate0
GenericList100
DocumentLibrary101
Survey102
Links103
Announcements104
Contacts105
Events106
Tasks107
DiscussionBoard108
PictureLibrary109
DataSources110
WebTemplateCatalog111
UserInformation112
WebPartCatalog113
ListTemplateCatalog114
XMLForm115
MasterPageCatalog116
NoCodeWorkflows117
WorkflowProcess118
WebPageLibrary119
CustomGrid120
SolutionCatalog121
NoCodePublic122
ThemeCatalog123
DataConnectionLibrary130
WorkflowHistory140
GanttTasks150
Meetings200
Agenda201
MeetingUser202
Decision204
MeetingObjective207
TextBox210
ThingsToBring211
HomePageLibrary212
Posts301
Comments302
Categories303
Facility402
Whereabouts403
CallTrack404
Circulation405
Timecard420
Holidays421
IMEDic499
ExternalList600
IssueTracking1100
AdminTasks1200
HealthRules1220
HealthReports1221
InvalidType-1

Is the Event registered in the Elements.xml?

When you add the event during the creation of the project the Receiver is automatically added to the Elements.xml. HOWEVER, if you add it later by typing it into the code page for the project, it will be missing from the Elements.xml. Therefore it is not registered and will not run.

You can either manually update the Elements.xml, or you can do it the easy way. Click on the folder that contains the Elements.xml (in this case it is simply EventsReceiver1) and look at its properties. You can simply select that it Handles whatever your event is by changing it to True. This will put the entry into the Elements.xml for you.

hope this helps...

# Thursday, August 04, 2011

Sharepoint 2010 - How to use List Events to Set a Column's Value using Visual Studio 2010 (C#)

The Problem

I came across this issue due to the fact that you cannot use a Choice Column in a Lookup Field. Basically I wanted to use a Lookup Column in a Calculated field.

No dice.

Look here -> http://www.myfriedmind.com/techBlog/2010/12/01/Sharepoint2010LookupFieldsWillNotAllowChoiceColumn.aspx for more info.

Setup for Solution

So what I ended up doing was using some of the nifty new features in Visual Studio 2010 and its integration with Sharepoint 2010, particularly its exposure of List Events. Leveraging this I was able to create a project that generates a new Column based upon other Columns. Because it of the way the system functions I can snag the data from the Lookup Column and use it. In effect I can code my on Calculated Column.

There are a number of good blogs on this, but why not have one more? <g> Plus I will talk about some extra stuff (like the best way to reference those Columns)...

Let us start with two lists - DataLookup and EventListenerTest.

DataLookup is very simply - it merely consists of the Title Column. Its sole purpose is to provide a Lookup Column to EventListenerTest. Let's populate it with four entries with the data "First DataEntry Lookup", "Second DataEntry Lookup", "Third DataEntry Lookup", and (of course) "Fourth DataEntry Lookup".

EventListenerTest consists of four Columns besides Title - a Single Line of Text Column named "SingleLineOfText", a Choice Column named "ChoiceColumn", a DateTime Column called (you guessed it) DateAndTime with a default of the current date and time, and a Lookup Column referencing the Title from DataLookup that is named "DataEntryLookup". Not very creative, but it gets the job done.

Our goal is to populate the Title Column with the text generated by combining the entries contained in the SingleLineofText, the ChoiceColumn and the DataEntryLookup with spaces in between. Basically [SingleLineOfText] & " " & [ChoiceColumn] & " " & [DataEntryLookup]. Were we to attempt to do this in a Calculated Column it would not work because the DataEntryLookup would not be available due to its being of the Lookup Column type. Please note there are 'workarounds' that involve tricking Sharepoint 2010 into allowing a Calculated Column to reference a Lookup Column. That is not what I am aiming towards. Incidentally, I chose the Title column to help show multiple ways to reference columns.

Creating the Project

Creating the Project in Visual Studio 2010 is cake.

  1. Create a new project and from within the Installed Templates. Select Sharepoint; 2010; then EventReceiver. Give it an appropriate name and click OK.

  2. On the next screen you have to decide whether to go sandboxed or farm.
    This is a bigger issue than at first glance. Normally I would recommend sandboxed for two reason. First, if you do go to the 'public cloud' you will need to have it sandboxed unless you are paying for your own box. Second, this should in theory minimize the amount of times that this program runs. Because EventReceivers are not assigned to specific lists just to ListTypes, they fire on Every matching ListType Every Time. It is much nicer to have it fire only on those Lists in the appropriate Site rather than on every List in your Web.



  3. Now you get to select the type of event(s) that you want to interact with. In this case you will want "List Item Events".
    We are going to select both "An item is being added" (ItemAdding) and "An item is being updated" (ItemUpdating). For demo purposes I am also going to scroll down and select "An item was added" (ItemAdded) and "An item was updated" (ItemUpdated).
    You also get to choose what type of list that you want these Events to be captured on. You most likely want to change your event source to be "Custom List". If we selected "Announcements" (the default) for example, our code would only run when Lists of the type Announcements Added or Updated to. See http://www.myfriedmind.com/techBlog/2011/08/17/Sharepoint2010ListEventCodeNotBeingTriggered.aspx.

Event "properties" - SPItemEventProperties

The project now displays with four overridden Methods - ItemAdding; ItemUpdating; ItemAdded; and ItemUpdated because you are inheriting from SPItemEventReceiver. Just as in any project, you can simply add more overridden events if you so choose at any time. HOWEVER, if you do this after the project has been created (and not through the wizard) then you MUST modify the Elements.XML file or these events will never be captured. There is a simple way to do this by modifying the properties of the folder that contains the Elements.xml file. See http://www.myfriedmind.com/techBlog/2011/08/17/Sharepoint2010ListEventCodeNotBeingTriggered.aspx for more info.

It is important to note that they all passed a single object - an SPItemEventProperties object referred to as "properties". Since we all refactor, we are going then simply pass that along to a common Method which we will call SetCalculatedTitle. There are two things to note here which we will utilize later. First, not all the data is populated equally depending on the SPReceiverEventType (eg ItemAdded vs ItemAdding). Second, we can determine what the SPReceiverEventType is from the SPItemEventProperties.

To demonstrate what each of these four events exposes we are going to add some code to this Method. The first thing we have to do is verify that we are in the correct List. This is achieved by checking the ListTitle property of the SPItemEventProperties object that we passed in. If it is the correct List, then we will look at particular aspects to see what each of the events are passed in.

Important Warning: changing the Title of the List will prevent this code from running. Unlike Columns, which can be referenced via their internal names (see http://www.myfriedmind.com/techBlog/2011/07/25/Sharepoint2010HowBestToReferenceAColumnFieldFromAnSPListItem.aspx for more on this), there is no Internal Name property of a List. There is a clunky workaround I will blog about later, but for now just cross your fingers and hope that your users do not rename the Title of the List.

The SPItemEventProperties object contains a number of properties, including

  • The name of the List Title
  • The Event Type (or SPEventReceiverType) such as "ItemAdding"
  • The SPListItem itself that is triggering the Event
  • An SPItemEventDataCollection containing the properties of the ListItem before the event completes (called BeforeProperties)
  • An SPItemEventDataCollection containing the properties of the ListItem after the event completes (called AfterProperties)

What are the properties for each event?

In order to answer that question I wrote the following bit of code:

        private void SetCalculatedTitle(SPItemEventProperties properties)
        {
            if (properties.ListTitle == "EventListenerTest")
            {
                SPListItem _listItem = properties.ListItem;

                SPItemEventDataCollection _beforeProperties = properties.BeforeProperties;
                SPItemEventDataCollection _afterProperties = properties.AfterProperties;

                bool _hasBeforeProperties = HasItems(_beforeProperties);
                bool _hasAfterProperties = HasItems(_afterProperties);


                string _singleLineOfTextFromItem;
                string _singleLineOfTextFromBeforeProperties;
                string _singleLineOfTextFromAfterProperties;

                if (properties.EventType != SPEventReceiverType.ItemAdding)
                {
                    _singleLineOfTextFromItem = _listItem["SingleLineOfText"].ToString();
                }
                if (_hasBeforeProperties)
                {
                    _singleLineOfTextFromBeforeProperties = _beforeProperties["SingleLineOfText"].ToString();
                }
                if (_hasAfterProperties)
                {

                    _singleLineOfTextFromAfterProperties = _afterProperties["SingleLineOfText"].ToString();
                }

                int _numberOfBeforePropertiesChanged = properties.BeforeProperties.ChangedProperties.Count;
                int _numberOfAfterPropertiesChanged = properties.AfterProperties.ChangedProperties.Count;
            }
        }

If you are curious, the HasItems was a simple static method I wrote to return a boolean as such:

        private static bool HasItems(SPItemEventDataCollection collection)
        {
            bool _hasItem = false;

            foreach (object o in collection)
            {
                _hasItem = true;
            }

            return _hasItem;
        }

Each of the four Methods calls SetCalculatedTitle and passes the properties object, like so:

       public override void ItemAdding(SPItemEventProperties properties)
       {
           SetCalculatedTitle(properties);
       }
       public override void ItemUpdating(SPItemEventProperties properties)
       {
           SetCalculatedTitle(properties);
       }
       public override void ItemAdded(SPItemEventProperties properties)
       {
           SetCalculatedTitle(properties);
       }
       public override void ItemUpdated(SPItemEventProperties properties)
       {
           SetCalculatedTitle(properties);
       }

So, what are the results? Let us say we create a new item, putting "Hi Mom" in the SingleLineOfText entry. We then update that item to change the SingleLineOfText to "Hi Dad".

ItemAdding

As you can see, the ListItem does not exist (it has not been added), there are no BeforeProperties, but there are AfterProperties. In fact, this is the only place where you can find out what is going on.

As you can see, the AfterProperties for the SingleLineOfText column is "Hi Mom". There is one major showstopper here, which I will also mention later, and that is that Lookup Columns (which contain a Key called LookupId and a Value called LookupValue) do NOT have their LookupValue set yet. They do have their LookupId, but it is only when the ListItem is instantiated that the LookupValue is then assigned. This will play a crucial role later as we shall see.

ItemAdded

By this time the ListItem exists. This is, of course, because the Item has been Added. There are still no BeforeProperties, but there are AfterProperties - in fact the same as in ItemAdding. Both the ListItem properties and the AfterProperties contain the same column information - they both show that SingleLineOfText is "Hi Mom". Also, unlike ItemAdding, the LookupValue of a Lookup Column has been set in the ListItem.

ItemUpdating

Here is where it gets interesting. The ListItem exists (of course). There are STILL no BeforeProperties, but there are AfterProperties. However the value of SingleLineOfText is different in the ListItem (reflecting the original value) and the AfterProperties (reflecting the new value). ListItem shows "Hi Mom", AfterProperties shows "Hi Dad". Again, like ItemAdding, the LookupValue of a Lookup Column is not set in the AfterProperties although its LookupId is. Note that the LookupValue of a Lookup Column exists in the ListItem, but it is for the original (not updated) value.

ItemUpdated

Unlike ItemUpdating, by this time it has already been Updated, and so the AfterProperties and the ListItem column information for SingleLineOfText both show "Hi Dad". Similar to ItemAdding the LookupValue of the Lookup Column has been set.

So, where do you set the value of Title?

Is it ItemAdding or ItemAdded? Do you want ItemUpdating or ItemUpdated?

The answer seems obvious. It is not. 

If you were paying attention above you will note that the common thread is AfterProperties. ItemAdding does not have the ListItem yet, and nobody has a BeforeProperties, but all have the AfterProperties set to the new values. Except, of course, if you have a Lookup Column.

Since we are going to be using a Lookup Column in our code, we need to create an SPFieldLookupValue object from the string that is stored in that Column. You then can access the LookupValue property to get the string you want to use in your code. You would like to do it this way:

                SPItemEventDataCollection _afterProperties = properties.AfterProperties;
                SPFieldLookupValue _dataEntryLookup =
                    new SPFieldLookupValue(_afterProperties["DataEntryLookup"].ToString()); 

But you can't.

The issue is that the AfterProperties contains the LookupId, but NOT the LookupValue. That LookupValue is not assigned until the Item is actually Added or Updated. It is only then that you can get the LookupValue from an SPFieldLookupValue object. So you have to do it this way:

                SPListItem _listItem = properties.ListItem;
                SPFieldLookupValue _dataEntryLookup =
                    new SPFieldLookupValue(_listItem["DataEntryLookup"].ToString());

This will not work in ItemAdding/ItemUpdating. This is because ItemAdding does not have a ListItem yet, and because the ListItem in ItemUpdating contains the old values. If the Lookup Column's value has changed then referring to the ListItem will only give you the old value, not the new.

This means that if you need to use a Lookup Column as part of your code, you can not use ItemAdding or the ItemUpdating without jumping through some ugly hoops. You can still use it for validation checking (using LookupID for example), but it gets messy real fast. Ultimately this means that if you have a Lookup Column that you are needing the LookupValue for you have to use ItemAdded and ItemUpdated. You could do some validation in the other two Events like I said, just do not expect it to be smooth.

So, you will need to use ItemAdded/ItemUpdated. As a result, the generating the new text would look something like this:

                SPListItem _listItem = properties.ListItem;
                SPFieldLookupValue _dataEntryLookup =
                    new SPFieldLookupValue(_listItem["DataEntryLookup"].ToString());
                string _newTextForTitle =
                    String.Format("{0} {1} {2}", _listItem["SingleLineOfText"],
                    _listItem["ChoiceColumn"], _dataEntryLookup.LookupValue);

Assigning it would be equally as simple you would think. What you want to do is assign it to the AfterProperties.

Remember those? The AfterProperties are what are assigned to the Added/Updated ListItem. For example, to assign a new Title, you can change it directly like so:

                SPItemEventDataCollection _afterProperties = properties.AfterProperties;
                _afterProperties["Title"] = _newTextForTitle;

Thus when the Item is Added or Updated it is assigned the new Title. The problem is that AfterProperties only apply BEFORE the item is Added or Updated. As a result while you can modify the AfterProperties in ItemAdding and ItemUpdating, You cannot in ItemAdded and ItemUpdated. Once the ListItem has been Added or Updated, the AfterProperties cannot be changed.

What about directly changing the ListItem itself in ItemAdded and ItemUpdated? Like so:

                SPListItem _listItem = properties.ListItem;
                SPFieldLookupValue _dataEntryLookup =
                    new SPFieldLookupValue(_listItem["DataEntryLookup"].ToString());
                string _newTextForTitle =
                    String.Format("{0} {1} {2}", _listItem["SingleLineOfText"],
                    _listItem["ChoiceColumn"], _dataEntryLookup.LookupValue);
                _listItem[new Guid("fa564e0f-0c70-4ab9-b863-0177e6ddd247")] = _newTextForTitle; // we use the Title Column's GUID for demo

We are definitely getting warmer. The only issue is that running this code, while it does not throw an error, also does not change the value of the Title Column. Why? Because the Events that we are running this in happen AFTER the ListItem has been changed. In order to get this change applied we need to call the SystemUpdate event on the ListItem, like so:

                   _listItem.SystemUpdate();

Except that this throws errors. Why? Because we are triggering the code AGAIN. The SystemUpdate method of a SPListItem updates the database, which would trigger an Event, correct? What we need to do is turn off Event notifications for this section of code, made the change, and turn then back on again

                    this.EventFiringEnabled = false;
                    _listItem.SystemUpdateUpdate();
                    this.EventFiringEnabled = true;

Now our code is using the ItemAdded/ItemUpdated Methods to get the values and update the Title Column.

Conclusion

In an ideal world there would be one process, one Event to rule them all. In this case you have options, which is not always a bad thing. The pivotal decision is whether you are using a Lookup Column in our code. If you are then you should use ItemAdded and ItemUpdated because the LookupValue of the Lookup Column is not set until after the changes have been made. If you are not using a Lookup Column, then you are free to use ItemAdding and ItemUpdating, just remember to use the AfterProperties and not the ListItem to get the Columns' values.

  • If using a Lookup Column in your code, using ItemAdded and ItemUpdated. Use the ListItem to get and set the Columns' values
  • If not using a Lookup Column, you can use ItemAdding and ItemUpdating. Use AfterProperties to get and set the Columns' values

Below is the basic code in which we are using ItemAdded and ItemUpdated:

   public class EventReceiver1 : SPItemEventReceiver
    {
        public override void ItemAdded(SPItemEventProperties properties)
        {
            SetCalculatedTitle(properties);
        }
        public override void ItemUpdated(SPItemEventProperties properties)
        {
            SetCalculatedTitle(properties);
        }

        private void SetCalculatedTitle(SPItemEventProperties properties)
        {
            if (properties.ListTitle == "EventListenerTest")
            {
                if (properties.EventType == SPEventReceiverType.ItemAdded ||
                    properties.EventType == SPEventReceiverType.ItemUpdated)
                {
                    SPListItem _listItem = properties.ListItem;

                    SPFieldLookupValue _dataEntryLookup =
                        new SPFieldLookupValue(_listItem["DataEntryLookup"].ToString());

                    string _newTextForTitle =
                        String.Format("{0} {1} {2}", _listItem["SingleLineOfText"],
                        _listItem["ChoiceColumn"], _dataEntryLookup.LookupValue);

                    // note that you could also reference the Title column as _listItem["Title"]
                    _listItem[new Guid("fa564e0f-0c70-4ab9-b863-0177e6ddd247")] = _newTextForTitle;

                    this.EventFiringEnabled = false;
                    _listItem.SystemUpdate();
                    this.EventFiringEnabled = true;
                }
            }
        }
    }

# Monday, July 25, 2011

Sharepoint 2010 - How best to reference a Column (Field) from an SPListItem

I have to give special recognition to Mike Morton at Microsoft for running down for me the fourth method below. I had chatted with him at Tech Ed specifically if there was a method other than the initial three and he contacted the SP Platform people and uncovered the best solution.

Please note that I am leaping both feet into the confusing Sharepoint lingo by calling what is referred to in the documentation as "Fields" by the commonly used phrase "Column". In the UI of Sharepoint they are referred to as "Columns", but in the dev environment of VS 2010 and the documentation they are refered to as "Fields". Please do not get confused -> Columns == Fields.


One of the fantastic additions to Sharepoint coding in sp10 is the exposure of List events, including the events for the Adding, Deleting and Updating of SPListItems. Coupled with the integration with Visual Studio 2010, this has produced a solution to at least one issue - the inability to use Lookup fields in a Choice Column (see http://www.myfriedmind.com/techBlog/2010/12/01/Sharepoint2010LookupFieldsWillNotAllowChoiceColumn.aspx). You can now manually do the work that the  In short you can use code to generate your a 'Calculated Field' from a selection of columns (and other stuff) and assign it to a Column of your choosing. Not to mention a whole lot more.

Before I post on how to programatically assign a value to a Column based on other Columns, I wanted to mention one issue that rears its ugly head - what is the best way to reference the Column(s) that you want to access?

There are three methods show by intellisense, plus a secret one (okay, not secret, but not explained through intellisense).

Let us say that you decide to create a new column in a list. You create a Column called "MyColumn", keeping to the best practice of not having spaces in initial Column names. It is the fourth Column in the list (not in the View, mind you. but the list). You then rename it to "This Is My Column". When it is created, it is assigned a new Guid by Sharepoint - in this case we will say fa564e0f-0c70-4ab9-b863-0177e6ddd247. Got that?

You now have a Column that has a Sharepoint assigned GUID of fa564e0f-0c70-4ab9-b863-0177e6ddd247; an Internal Name of "MyColumn"; a Display Name of "This Is My Column"; and it is currently the fourth Column in the List (not to be confused with a View).

As a result there are four ways that you can retrieve this Column from an SPListItem object in that List. Let us say we have an SPListItem which we have retrieved and called _listItem (SPListItem _listItem = properties.ListItem). We can then get the value of the Column we just created:

  1. Via the Column's GUID - ex: _listItem[new Guid("fa564e0f-0c70-4ab9-b863-0177e6ddd247")]
  2. Via the Index of the Column - ex: _listItem[3] // (remember that this is zero-based, so this is the fourth Column)
  3. Via the Display Name of the Column - ex: _listItem["This Is My Column"]
  4. Via the Internal Name of the Column - ex: _listItem["MyColumn"]

The fourth option - using the Internal (or original) Name of the Column is actually folded into the third, although intellisense does not display that. As noted at http://msdn.microsoft.com/en-us/library/ms464204.aspx - the runtime will look FIRST for the Internal Name and THEN for the Display Name. More on that later.

There are obvious issues for each of these means.

Via the Column's GUID

The real problem here is, of course, that each time the Column is created on a new server it is assigned a new GUID. That is, after all, the purpose of GUIDs. This means that if you are using this method on your dev box, it will be broken once it moves to a new server. In addition, if a server is lost and recreated (not restored), the columns will probably be reassigned new GUIDs. A restore should maintain the old GUID since that is stored in the database. The point is that each creation of the Column will result in a different GUID.

It is very important to note that this does not apply to the default fields - as noted at http://sharepointmalarkey.wordpress.com/2010/10/12/sharepoint-internal-field-names-sharepoint-2010/. The Title field, for example, will ALWAYS have a GUID of fa564e0f-0c70-4ab9-b863-0177e6ddd247 no matter how many times it is created.

One possibility is to change the GUIDs when it is published to the production server. One would need to find the particular Fields GUID that the production server has assigned it, modify the code, and then publish it up to the production server. Messy, to say the least.

Via the Index of the Column

To be brutally honest, this is nice to have but fairly useless for our purposes. Unless you can guarantee that no one will ever reorder the columns you can let this one go. It is useful for iterating through the Columns, not for finding a particular Column.

Via the Display Name of the Column

The Display Name is the name that is, quite simply, the name of the column that is displayed. It can be changed (unlike Internal Name). Very, very handy. Unfortunately the only way to guarantee that this works is to guarantee that the users never, ever change the Display Name. While you can restrict the ability of users to be able to change column names via permissions, you can never really guarantee that it will not take place. In addition the ChangeFieldName event is not exposed, so there is no way to catch this at present. Useful for demo, but not necessarily for development. There is no real reason to use this when you can choose to go ...

Via the Internal Name of the Column

The Internal name is the initial name given the Field. If you create a Column and call it "MyFirstColumn" and then change its Display Name to "Other Data" the Internal Name is STILL "MyFirstColumn" and the Display Name is now "Other Data". No matter how many times you change the Display Name, the Internal name will NOT change for the life of the column.

When you pass a string as the Key to find the Column in an SPListItem it looks FIRST for the Internal Name and THEN for the Display Name. From the article http://msdn.microsoft.com/en-us/library/ms464204.aspx - "The runtime will search first through the internal names of the list item’s fields for the specified string before searching the display names." So it will find "MyFirstColumn" before finding "Other Data".

This is another reason to use this method - it reduces retrieval time.

This means that if you know the Internal Name you can probably code to that with no issue. Getting the Internal Name from an existing field is fairly simple. Again, thanks to Mike for the advice. Thanks to the nifty integration with Visual Studio 2010, you can use Server Explorer to open up the List that you are interested in. Connect the server via Sharepoint Connections, and then drill down until you find the Column that you are interested in. Right click and select Properties.

In the Properties panel you will see the Internal Name, clear as day. In this instance, although the Display Name is "Favorite Band" we discover that the Internal Name is "WhoDoYouLike" as shown below.

So, what is the best way?

If it is a preexistent Column (such as Title), then you should probably use the GUID.

If it is a new Column, then use the Internal Name. As always, it is generally considered best practice to name the Columns without spaces and then change its Display Name.

Now, what happens if someone changes the name of the List? That is a murkier solution I will talk about later...

Hope this helps...

# Tuesday, June 07, 2011

Sharepoint 2010 Modal Popup still not displaying error information even though web.config has customerrors="off"

I was working on a BCS project via Web Services (more in other posts) when I ran across a frustrating dead end. When I clicked on the "Edit" for an External List I got a modal popup informing me that there was an error. It was the standard notification that advices you to change the customerrors setting in web.config to "RemoteOnly" or to "Off".

Since this was a dev machine I went into the web.config file for the site under is subfolder (...\inetpub\wwwroot\wss\VirtualDirectories\80) and set the customerrors line to "Off". I reloaded the site and tried again.

DOH!!!

I dug around, using different tools, trying to finding different means to find out what was wrong, but ultimately I wanted to know why my customerrors setting was not sticking. Luckily for me (and you) there are bright people out there and Greg Galipeau discusses this in his post at http://www.greggalipeau.com/2010/11/01/sharepoint-2010-customerrors-mode/

The long and the short is that there are TWO web.configs. It appears that the _layouts subdirectory (this form is located in "../_layouts/listform.aspx") has ITS web.config, which only actually changes a handful of things. One of them, however, is customerrors...

It is located at \Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS (ie within the "14-hive"). Changing the setting in that web.config to <customErrors mode="Off" /> caused the issue to successfully appear in the Modal popup, in this case an issue with the Edit Form:

You should especially pay attention to the fact that modifying the website's web.config (vs the Layouts folder) will have no effect upon the popups. The web.config settings in the LAYOUTS folder will OVERRIDE the settings in your website. If the Layouts has customerrors mode="off" and your website has customerrors mode="on", the _layouts will still display the error.

You could remove that line from the web.config in the Layouts folder, and then it would inherit the settings from your site, but don't tell anyone I suggested it...

Hope that helps...

# Thursday, April 07, 2011

Sharepoint 2010 Title Column GUID

LOL! In hunting down something else I stumbled across this blog entry -> http://sharepointmalarkey.wordpress.com/2010/10/12/sharepoint-internal-field-names-sharepoint-2010/ which has all the standard columns (including Title) with their GUIDs!

AWESOME!!!

Just an fyi...

# Tuesday, April 05, 2011

Failed to instantiate file ... from module ...: The specified list does not exist. - Sharepoint 2010

Working on creating a web template system to create a designed site and ran into the above error. Found this note -> http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/27ac36ca-3d3a-47eb-9fc6-ee1b1846b8a3/

Basically you need to change the entry in the 'File' section from 'GhostableInLibrary' to 'Ghostable'

<File Url="Default.aspx" Type="Ghostable />

# Friday, February 04, 2011

Sharepoint 2010 - The list can not be displayed in Datasheet view for one or more of the following reasons:

I have just upgraded my desktop, and so decided to install Office 2010 (why not?) rather than keep the old Office 2007 I had. This is especially important because InfoPath forms on Sharepoint 2010 are in InfoPath 2010. And of course, more the fool me, I decided to go 64-bit. After all - my machine is 64-bit; Sharepoint 2010 is 64-bit - why wouldn't I?

The answer is in the error message below, which I received when I tried to open a simple SP2010 List in Datasheet view

This is triggered, so I gather, from the fact that my Office 2010 is 64-bit, and Sharepoint 2010, although being a 64-bit version, only talks 32-bit to its clients.

Now before you pull out your hair and go on a rant about how STUPID Microsoft appears to be in doing this, Let me assure you there is a simple workaround. You simply need to install the "2007 Office System Driver: Data Connectivity Components". You can get that at http://www.microsoft.com/downloads/details.aspx?familyid=7554F536-8C28-4598-9B72-EF94E038C891.

If you still want something to rant over - read the KB article that suggests this at http://support.microsoft.com/kb/2266203, specifically the part (and I quote) "...we recommend that you uninstall the 64-bit version of Office 2010 and install the 32-bit version of Office 2010."

I have been very impressed with Sharepoint 2010 and am busy coding my little heart out, but THIS is just plain dumb...

# Wednesday, December 01, 2010

Sharepoint 2010 Lookup Fields will not allow Choice column

One of the vast improvements in Sp10 is that when you add a lookup column to a list it can drag along additional fields that it is tied to. In Sp07 you had to use a third-party product to get the same results. In the RTM version of Sp10 you could include columns that were 'Choice' columns, but this is no longer the case. In fact you can not use a 'Choice' field at all.

This is a 'known issue' per Lily Wu (from Aug 31, 2010) -> http://social.msdn.microsoft.com/Forums/en/sharepoint2010general/thread/5a80988a-6b37-4454-957b-856ea16b2e60

I apologize for taking so long to get around to it, but I have a post that discusses how to write code to do this -> http://www.myfriedmind.com/techBlog/2011/08/04/Sharepoint2010HowToUseListEventsToSetAColumnsValueUsingVisualStudio2010C.aspx

Hope this helps...

# Tuesday, August 17, 2010

Sharepoint OWA Webparts Prompting for Username And Password

If you want to use OWA webparts with Integrated Authentication or Basic and have it default to the user that is logged on, the steps are simple - leave the username blank (see below).

But if you have done that you may be surprised to find that it continually prompts you to log in on that page EVEN THOUGH YOU ARE ALREADY logged on.

Not putting in the info gives you a beautiful 401 error: 

Luckily the resolution is simple.

What you want is that you will be logged on to the mail server with the current user name and password. But if you open up the security settings on your browser you will find out that this is not the option.

There are two ways to resolve this - both involve changing the setting. You can either change the zone that it defaults to (ie make Local Intranet always do 'Automatic logon with current user name and password') or you can put the mail server in the Trusted Zones.

I like the latter.

Go into the Securities tab, click on 'Trusted Sites' icon and then click on the 'Sites' button.


Once you are in there you can add the FQDN of the mail server (since you will be using its cert)...

Voila!!! 

Note: if you want to do this on a larger scale I would suggest you turn to your handy-dandy Group Policy editor. You can find what you are looking for User Configuration / Windows Settings. I will leave the rest of the steps up to you...

# Tuesday, March 16, 2010

ISA 2006, Sharepoint 2010 giving HTTP 500 internal server error on HTTP Filter

Recently when playing around with the Sharepoint 2010 beta I extended a site to use Forms and passed that through ISA 2006.

This is all very basic stuff, there are a number of good references on how to set this up, but what I did not expect was the http 500 internal error on my browser (see below).

The solution was to modify the HTTP filter (egad! an error message that actually gives the correct problem!) within ISA for that Rule (right-click the rule and select "Configure HTTP") and uncheck "Verify normalization" (see image below). I do not know if this is restricted to Sharepoint, but I suspect that will all the razzle-dazzle that SP2010 is trying to pull off it is tripping over the big feet of ISA...

# Friday, March 12, 2010

Sharepoint 2010 Configuration Wizard "Failed To Register Sharepoint Services" with System.Security.Cryptography.CryptographicException Object Already Exists

Working on the SP2010 beta I bumped into an issue with search. I decided, after various attempts to fix it different ways, to rerun the Sharepoint 2010 Products Configuration Wizard. But when I did I ran into an error on Step #5 - namely a System.Security.Cryptography.CryptographicException of "Object Already Exists".


This was verified by checking the logs. I tried many, many things to resolve it, including making sure "Network Service" had full control over the 14-hive, per this blog and setting up Network Service using the aspnet_regiis -SampleKeys, etc. I even disabled the UAC (see my earlier post for an explanation).

No dice.

The resolution lay, as you may be suspecting, in messed up perms on the RSA folder, specifically C:\Program Data\Microsoft\Crypto\RSA\MachineKeys. I had checked to the RSA level and Administrators had full perms (I was logged on as with an Administrative account) but I had not taken the next step and checked MachineKeys.

Turns out that that folder had removed all perms from Adminstrators. I ended up having to take ownership of the folder and give Admins full perms again. Sure enough - it worked...

As a bonus it DID fix my Search problem (I was getting "The search request was unable to connect to the Search Service.").

Maybe.

Sharepoint 2010 Products Configuration Wizard gives you "Unhandled exception" 0x80070005 (E_ACCESSDENIED)

Trying to run the SP 2010 Config Wizard to resolve a Search issue I ran into the problem shown below.



The resolution was that I was logged in with an account that was not used in the SQL database (remember you need the perms)...
# Friday, February 05, 2010

Sharepoint 2010 Beta and PDF Icons

Look here for some good instructions for adding icons for file types (from foxit software who make a pdf search filter).

http://www.foxitsoftware.com/pdf/ifilter/installation

Remember to make the icon 16x16. Here is one you can use...