Wednesday, October 6, 2010

Accessing the UI thread in Silverlight

I’m creating a separate class where I want to move all related Client Object Model (COM) code.

In my case for the COM code to work it must update the UI thread. To accomplish this I had to move the reference from the main page, which was apparently passing through the Deployment object, to explicitly calling the Deployment object.

So in the case of the main page or I suspect any xmal pages code behind use this line of code in the ClientRequestSucceededEventHandler method:

this.Dispatcher.BeginInvoke(updateUI);


For separate classes to gain access to the UI thread use this line of code in the ClientRequestSucceededEventHandler method:

Deployment.Current.Dispatcher.BeginInvoke(updateUI);



Reference:
http://www.go4answers.com/Example/error-invalid-cross-thread-access-48335.aspx
Using Silverlight Object Model: http://msdn.microsoft.com/en-us/library/ee538971.aspx

Tuesday, September 28, 2010

Silverlight Export to Excel

The latest thing I’ve been working on is exporting to Excel from my Silverlight Indicator.

With Silverlight 4 there are two problem domains, In Browser and Out of Browser.

The Out of Browser mode is dead easy using Automation Factory. For it to function it does require the Silverlight App to be locally installed with elevated permissions. There are several examples out there, on the web, of this type of implementation now I leveraged the approach posted by Pradeep at c-sharecorner.com for my application, see his code below. This is a great solution that opens the exported data in an excel spreadsheet.


Solution using Out of Browser Mode
Add reference to Microsoft.CSharp.dll to the project.


using System.Runtime.InteropServices.Automation;
…

///
///This code has been leveraged from the following site:
///http://www.c-sharpcorner.com/UploadFile/pchandraker/1899/
///
///

private void btnExport_Click(object sender, RoutedEventArgs e)
{
dynamic excelApp;
excelApp = AutomationFactory.CreateObject("Excel.Application");
excelApp.Visible = true;
dynamic workbook = excelApp.workbooks;
workbook.Add();
dynamic sheet = excelApp.ActiveSheet;
dynamic cell = null;
int index = 1;
foreach (Employee emp in EmployeeGrid.ItemsSource)
{
cell = sheet.Cells[index, 1];
cell.Value = emp.EmployeeName;
cell = sheet.Cells[index, 2];
cell.Value = emp.EmployeeId;
cell = sheet.Cells[index, 3];
cell.Value = emp.Department;
index++;
}
}

Reference links –
Automation API - http://msdn.microsoft.com/en-us/library/ff457794(v=VS.95).aspx
More documentation - http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.automation.automationfactory(VS.95).aspx
A slightly different implementation - http://www.codeproject.com/KB/silverlight/SL4InteropWithExcel.aspx
A similar implementation - http://deepumi.wordpress.com/2010/06/01/export-datagrid-to-excel-in-silverlight-4-0/

Solution using In Browser Mode

With the Out of Browser Domain covered, I needed to tackle the In Browser Domain. To my surprise there wasn’t as many solutions as I thought there would be out there. Exporting a datagrid to excel would seem like a common enough task. Though I did find one gem in the rough Raelango on codeproject.com had posted a nice solution that works great if the columns are TextColumns or are TextBlocks in a template column. It defiantly got me pointed in the right direction. You can see his solution here: http://www.codeproject.com/KB/silverlight/SilverlightDataGridExport.aspx

I took a similar approach though I ended up customizing the code to fit my customized data types. It led to a nice solution which saves to an XML or CSV file based on the user choice through a standard save dialog.

Thursday, September 23, 2010

Libraries for Client Object Model

Ok this falls in to information I’ve had to look-up a couple times now. So I’m posting this to my blog for quick reference in the future.

Libraries required for SharePoint development using Client Object Model

The two files for Silverlight are:
Microsoft.SharePoint.Client.Silverlight.dll
Microsoft.SharePoint.Client.Silverlight.Runtime.dll

They can be located on the server at %ProgramFiles%\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ClientBin

For sandbox solutions you need:
Microsoft.SharePoint.Client.dll
Microsoft.SharePoint.Client.Runtime.dll

These are located on the server at %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\ISAPI

Getting the URL Parameter Using C#

As I’ve been working with the SharePoint COM API in Silverlight more things that were really hard to do or nearly impossible to do with SharePoint Designer (SPD) have become easier. One of the first things I need to do was link the Silverlight applications and my existing pages together which I felt was really easy to do by passing Query String Parameters.

This is really easy to do in C# with the Windows.Browser namespace.

Here is the method I use to accomplish this.

private string getURLParam(string key)
{
string value = "";
HtmlPage.Document.QueryString.TryGetValue(key, out value);
return value;
}

Now I can provide whatever key I would like to consume, in my case a row ID so I know which record to query in the SharePoint list.

Saturday, September 18, 2010

Alien Earth Review

Alien Earth by Megan Lindholm

Overall Grade C

This book takes place in a dystopian future long after the earth had been abandoned due to humans killing the planet. Humans are assisted in leaving the planet by the Arthropiana who travel in Beastships which are capable of interstellar travel.

The story is centered on a human crew of the Beastships who are traveling back to earth and the interaction with the Arthropiana co-captain.

Unfortunately the story seemed fairly predictable from plot to the characters, though the character development was paced ok. The one thing I liked, even though I knew how it was going to end by about halfway through, was the ending I felt it really delivered though getting there took a very predictable path.

http://www.meganlindholm.com/novels/alien-earth/

Friday, August 6, 2010

Setting-up SP2010 Dev. Environment (Win 7)

For those that are interested in developing for the SharePoint 2010 Environment to either build a sandbox or standalone solutions here is a quick summary of how to get the development environment set-up for Win7.

Please note that this is a multi-hour process of install / patch / install ... but it is worth it being able to dev for the SharePoint Environment.

• Excerpt from Directions here:
  – http://msdn.microsoft.com/en-us/library/ee554869(office.14).aspx
• Pre-install
  – WCF Hotfix for Microsoft Windows
   • http://go.microsoft.com/fwlink/?LinkID=166231
  – ADO.NET Data Services Update for .NET Framework 3.5 SP1 for Windows 7 and Windows Server 2008 R2
   • http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=3e102d74-37bf-4c1e-9da6-5175644fe22d
  – Microsoft Office 2010 Filter Packs
   • http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=5cd4dcd7-d3e6-4970-875e-aba93459fbee
• Install SharePoint Server (iso can be downloaded from MSDN)
  – Note: The configuration file for the instalation has to be altered. (See full directions)
• Install SharePoint SDK:
  – http://www.microsoft.com/downloads/details.aspx?FamilyID=f0c9daf3-4c54-45ed-9bde-7b4d83a8f26f&displaylang=en

If you already have VS2010 installed no other action needs to be taken. If you don't then you will need to install VS2010.

Thursday, July 29, 2010

Large List in SP2010

This is a long post on a problem with SharePoint 2010 that I worked on over the last week. Centered around understand and working with Large Lists in custom forms. You can skip to the bottom to see the summary of the solution I took.

The Problem:
The Original Error: This view cannot be displayed because it exceeds the list view threshold (5000 items) enforced by the administrator.

This single error led me on quite the educational trip. My first reaction crap my web application is broken. Then I mailed the server administrator asking that the limit be increased, complaining how my solution worked in MOSS. :) Luckily I was barely over the 5K limit so deleting some records let me drop below the 5K limit but I had problem with the application and I needed a way to test it while allowing my customers access to their data.

This led to my first workaround:
- Set the selectcommand to “<View></View>”,
- Edit the asp:Parameter MaximumRows and set it to 5K.
- Then apply xslt filtering.
Wince like I did, but it allowed me to work on the site w/o further disrupting my customers activities. There a lot of reason this is a no-no, performance being the biggest one.

Now I could work, experiment, test on the site / list. The server administrators got back to me after I had found this work around and asked me to continue pursuing a solution as MS would one day come back and tell us to set the threshold setting back to default thus putting us right back to square one. I’ll get back to why the administration team did the right thing here. Even though it seems like the simple answer to increase the threshold, DO NOT DO IT! Many thanks to the administration team for keeping me focused on delivering the right solution.

Before I get to that let me explain to those that may be yelling at the screen why didn’t you have a test site and unfortunately my site / application is very dependent on work flows and I have yet to find a good way to migrate those from site to site.

So back to the education, well we were early adopters and I missed the information about large lists and list throttling. Saw the information that the list can contain about 50 mil records, awesome!!...Missed the point about only being able to work with 5K at a time, though I never intended to even work with that large of a number of records.

Root causing the Issue:
Now I had to start scoping the problem I knew two things once a list crosses 5K records it now becomes a large list. What worked on a regular list no longer seems to work on a large list and I can only work with 5K records at a time and my exiting filters were not working before the records were being pulled.

So I needed to understand what a large list was:
- Which led me to this page: http://msdn.microsoft.com/en-us/library/ff798465.aspx
-- The best resource I found was a paper MS wrote about large lists titled “Designing Large Lists Maximizing List Performance” and can be downloaded here: http://www.microsoft.com/downloads/details.aspx?FamilyID=fd1eac86-ad47-4865-9378-80040d08ac55&displaylang=en
--- I was a bit shocked when the doc called out that most users when first faced with this problem are tempted to increase the threshold and it explained why not to take that approach in technical details. (it’s not every day that you can point at a doc and say I behaved exactly that way :) )
-- The second best resource was the help doc (I believe this is a replication of their online help documentation)- http://sharepoint.microsoft.com/blogs/GetThePoint/Lists/Posts/Post.aspx?ID=303

Unfortunately these papers didn’t really deal with my problem exactly. Though it begun to point me in the right direction and to be aware of some of the side effects of the list being a large list and explain what I was experiencing.

Some side effects or symptoms that a list has passed the large list threshold and become a large list or at least what I have experienced:
• Filters that worked previously no longer work
• Sort and filter functionality no longer works
• Some views may not work
• Count on list views will not work

Possible Permanent Solutions:
I first tried a query filtered with an indexed column, according to the documentation this is supposed to be the Holy Grail fix. Unfortunately this did not work as expected and still got the threshold error. So I abandoned this approach, I’ve head numerous issues with DFWP since I migrated to 2010 I figured this was one more thing that was neglected by MS and I’d have to file another bug against 2010.

I next compiled a list of potential workaround with a help of my site / application architect.

- Content iterator
-- http://msdn.microsoft.com/en-us/library/ff798376.aspx
-- Code solution
- Partitioned View
-- http://msdn.microsoft.com/en-us/library/ff798344.aspx
-- Seems to only apply to SQL data sources
- Managed Metadata
-- Will require adjustment to the list
-- Should have been applied at design phase
-- Will require a lot of pre-work in planning before implementing
- Content Query Web Part
-- To enable it
--- http://vspug.com/ssa/2010/02/06/sp2010-tip-content-query-web-part-missing-in-sharepoint-2010/
--- http://social.msdn.microsoft.com/Forums/en/sharepoint2010general/thread/4cfcdb20-0e1e-4651-bfda-008fe554696e
-- To Use it
--- Dated write up - http://blogs.msdn.com/b/ecm/archive/2006/10/25/configuring-and-customizing-the-content-query-web-part.aspx
--- Newer info - http://blogs.msdn.com/b/ecm/archive/2010/05/14/what-s-new-with-the-content-query-web-part.aspx
-- Customize it
--- http://msdn.microsoft.com/en-us/library/aa981241.aspx
--- http://msdn.microsoft.com/en-us/library/ms497457.aspx
- Access Services
-- Dead end
- Re-architect the site using folders and custom content types
-- This would enable easier filtering that would not hit the threshold
-- Similar implementation to Managed Metadata
-Bring in MS SharePoint consultant to solve our problems
-- This was added for completeness… :)

The Final Solution:
While we are eventually going to go to a coded solution hosted in our sites Sandbox we are not there yet. So I focused on the lowest code solutions. I started working with the CWWP (Content Query Web Part). It was the first time I have used it I can see how it can be very useful for someone who didn’t want to edit the XSLT directly. Though it does require some knowledge in how the list is structured. Then I read that the CQWP is an extended DFWP and it was working so it led me back to my CAML Query. I remembered a line in one of the documents that it said when filtering a query for a large list always use an AND operator as an OR will rarely limit the results below the threshold. I knew my CAML Query didn’t have any operators so I just gave it a try using a static true statement with my filter on an indexed column so that I would get an AND operator in the select command.

The static statement is also using an Indexed column (ID) and it is simply comparing to see if it is greater than zero (which is always True).

The CAML Query that works:

selectcommand=
"<View>
 <Query>
  <Where>
   <And>
    <Eq>
     <FieldRef Name="PN_ID"/>
     <Value Type="Text">
      {PN_ID}
     </Value>
    </Eq>
    <Gt>
     <FieldRef Name="ID"/>
     <Value Type="Counter">
      0
     </Value>
    </Gt>
   </And>
  </Where>
 </Query>
</View>"

The CAML Query that did not work (Even though it is using an Indexed Column):
selectcommand=
"<View>
 <Query>
  <Where>
   <Eq>
    <FieldRef Name="PN_ID"/>
    <Value Type="Text">
     {PN_ID}
    </Value>
   </Eq>
  </Where>
 </Query>
</View>"


Summary:
For large lists, do your best to plan ahead.
Try to determine which potential solution is the right one for your audience.
See the “Designing Large Lists Maximizing List Performance” document
If the right solution is to use the DFWP then make sure that you:

  • Have at least 1 indexed column you can filter on effectively
  • Index Before your list is over the threshold preferably
  • Use two filter criteria’s on Indexed Columns to ensure that you have an AND operator in your CAML Query.