in

Dot Net Mafia

Group site for developer blogs dealing with (usually) .NET, SharePoint 2013, SharePoint 2010, Office 365, SharePoint Online, and other Microsoft products, as well as some discussion of general programming related concepts.

Kyle Kelin on .Net

  • Some part of your SQL statement is nested too deeply

    I received the following error last week:

    Some part of your SQL statement is nested too deeply. Rewrite the query or break it up into smaller queries.

    Here is a good article describing the problem: http://rapidapplicationdevelopment.blogspot.com/2007/05/caml-nested-too-deep.html

    The article describes the cause of the error was trying to insert a large amount of list items in a batch query. The solution is to break up the batch into smaller chunks. However I was doing a select query. After some googling and coming up short, I copied the CAML query into a text file and took a look at it. The query was several hundred lines long. It seems that the where clause of the CAML query was being added dynamically inside a loop like this

    foreach (HistoryItem distinctItem in distinctItems)
    {
                 spQuery.Or(HistoryListColumns.Number, SPFieldTypes.Text.ToString(), distinctItem.Number);
    }

    This loop builds up a CAML query by adding an OR element for each item in the distinctItems collection. This worked fine until distinctItems grew to over 1,000 items making the resulting CAML query too long for SharePoint/SQL to parse it. The simple solution for me was to break distinctItems up into subLists of 200 items and create separate CAML queries for each then combine the results.

    So remember if you need to dynamically build your CAML queries pay attention to the size and how big the query could possibly get.

  • Who the Hell Wrote This?

    A colleague yesterday showed me a cool tip with TFS that I would like to pass along. If you have a code file open you can right-click to the left of the code in the gutter, under the source control menu, select the Annotate option. It will open the file up in a new file and show you who wrote that line.

  • Creating a List from a List Template

    I recently struggled with this code and thought I would document it here.

    SPListTemplateCollection listtempColl = web.ListTemplates;

                           SPListTemplate myListTemplate = listtempColl["Random List Template"];
                           web.Lists.Add("MyList", "my list description", myListTemplate );

     

    Pretty simple code. I use the ListTemplate collection of the SPWeb to get a template I have already deployed. I then use that template in the Add method to create the list instead of one of the built in templates.

  • Post Build Actions Are Evil

    This post is in response to the last SharePoint project I was on. Though this wasn’t the first time I have seen this. The developer was using wsp builder and a file called PostBuildActions.bat that was executed when they built their solution. This allowed him and other developers to simply hit F5 to build the solution and deploy it locally to their SharePoint environment. The problems started when the solution grew. It was up to 19 projects when I saw it and most projects had a bat file that was copying assemblies and ascx files after building in order for the wsp builder to work. As you can imagine this was pretty complex and unmanageable. And the build times were over 5 minutes long. Build times this long really interfere with a developers flow. I would hit F5 got get a cup of coffee or minimize the vpc and surf the web. Not a very good use of my time so I decided to cut this down.

    There are three solutions that you could take:

    1. Create additional build modes to Debug and Release

    Use Debug and Release for compile only and create a DebugDeploy and ReleaseDeploy that will then call your PostBuildActions.bat. The does speed up the process because we now can just build if we wanted. But it still to me seemed difficult for a new developer to catch on.

     

    2. Create a manual deploy file

    This is the method I chose. I removed all post build actions and copied those files into one large bat. I ended up creating two bat files, one called buildwsp.bat that copied all the files necessary assemblies and ascx files and included the wsp builder commands to create the wsp file. Next I created a file called deploy.bat that would rectract and redploy the solution package. The process was hit F5, then click buildwsp, then finally deploy. I had the two bat files on my task bar for easy use. This cut down the total deployment to about 2 minutes but it also gave me the flexibility to quickly build in just under 30 seconds.

     

    3. Use MSBuild

    I didn’t use MsBuild in this situation because I didn’t have a lot of time and I don’t know MSBuild. For my next SharePoint project though I am going to use this. I think this could give me the speed and flexibility I have been wanting. There are even some MsBuild templates for SharePoint out on CodePlex.

  • The .NET Framework version 4 cannot be installed because the .NET Framework version 1.0 is already installed on your computer

    I ran into this error message while trying to install the .NET Framework 4.0 Beta. I went into Programs to remove it and it wasn’t listed. Hmmm. So the first thing I did was download this tool:

    http://www.raymond.cc/blog/archives/2008/11/06/how-to-check-what-version-of-microsoft-net-framework-is-installed-in-computer/

    Run in and it will tell you which versions of the .NET Framework you had installed. Sure enough 1.0 was listed. So a quick google search brought me to this tool that removes versions of the .NET Framework.

    http://cid-27e6a35d1a492af7.skydrive.live.com/self.aspx/Blog|_Tools/dotnetfx|_cleanup|_tool.zip

     

    Just a quick note that this comes with no warranty. It worked for me but the cleanup tool is messing with the Registry so do so at your own risk.

  • Improving This Blog

    I winding down on my current project and decided to spend some time improving my blog. The first step was downloading Live Writer. Using Live Writer instead of Word should reduce the friction of posting. In theory this should make me post more frequently.

    Another thing I did was sign up for Technorati which requires me to post their link here
    <a href="http://technorati.com/claim/j6277u6ajx" rel="me">Technorati Profile</a>

    And the final step is to clean up my online presence a little bit. I started by updating bio on this blog but will also do that on other sites like twitter, delicious, linkedin, and facebook. And see if I tie all these together while making them consistent.

  • Slides and Code from SharePoint Saturday

    I ended up doing 3 sessions this past Saturday at the Tulsa School of Dev/ SharePoint Saturday put on by David Walker. I did two end-user sessions right after lunch, Document Library Basics and Introduction to InfoPath. After those I did a session over Unit Testing SharePoint with TypeMock. The turnout for that talk was smaller than I would have liked since David put me up against a Silverlight 3.0 talk. At the bottom of the post you will find slides and code for the unit testing session. If you want the InfoPath slides or example code just email me.

    DotNetMafia also had our second Beer and Code (SharePint) event.  Despite the snow, we still had some people turn out and we had a good time with plenty of food and beverages.  Our next event will be during Tech Fest 2009.  Thanks again to TekSystems for sponsoring the event.

  • Speaking In Tulsa This Saturday

    SharePoint Saturday is coming to Tulsa this weekend and I'm delivering two sessions. The first is an introduction to InfoPath and the second is Unit Testing SharePoint Code using TypeMock.

    Introduction to InfoPath
    New to InfoPath? This session will introduce you to InfoPath 2007. It will show you how to use the basic features of InfoPath to quickly and easily create data entry forms. You will learn how to bind dropdowns to SharePoint lists and xml documents. Also you will learn how to publish your forms to SharePoint so your users can fill them out and submit them through the browser.

    Unit Testing Custom SharePoint Solutions with TypeMock
    SharePoint solutions are made up of code and should be tested just like any other code base. Unfortunately some of the architecture choices made in the SharePoint Object Model limit a SharePoint developer's ability to unit test their code. This session will give an overview of mocking in general and then dive into how to use TypeMock to mock difficult dependencies like SPWeb and SPList. The session will also cover other types of testing besides unit testing including manual and integration tests.

    For those of you that were at Tech Fest last year, you might have heard about the epic Beer and Code event brought to you by DotNetMafia.  Well DotNetMafia is doing it again for SharePoint Saturday.  Beer and Code will be at Dirty's Tavern (just like last time) located at 325 E 2nd St (2nd and Elgin – Downtown Tulsa).  Update: We now have a sponser to pay for beer and food. Thanks Tek Systems!

  • Wrapping a SharePoint Choice Column with a C# Enum

     

    One thing I like to do in my SharePoint code is wrap the SharePoint Object Model code when I access a particular value in a Sharepoint list item. I do this so I can pretend like I'm not working with the SharePoint Object Model. :) I had a couple of choice columns that were represented as Enums in my code base this week. I wanted to share what that code looks like in case someone else might find it useful.

     

    The first method GetEnumValue is the method I am calling from my Data Access Layer (could be from the user control if you have fewer layers. The method takes the SharePoint listitem and the name of the column. I used generics in this method to make it more flexible so that it would take any Enum type so I wouldn't have to write a method for each Enum.

     

     

    public static T GetEnumValue<T>(SPListItem result, string columnName)

    {

    string value = (GetItemValue(result, columnName));

    return (T)Enum.Parse(typeof(T), value);

    }

     

    In the above method I used the method called GetItem. I use this little utility method to retrieve the value from the list item column

     

    public static String GetItemValue(SPListItem listItem, string columnName)

    {

    string value = string.Empty;

     

    try

    {

    var itemValue = listItem[columnName];

    if (itemValue != null)

    value = itemValue.ToString();

    }

    // catch ommitted for this examples

    return value;

    }

     

     

    Here is how you would use the above GetEnumValue method. The Enum type is DocumentType and the column in SharePoint is also named DocumentType. Now you will need to wrap this line in your code that will access the list item. I will let you google that. There are plenty of posts on that.

    documentType = Utilities.GetEnumValue<DocumentType>(listItem,"DocumentType");

     

    Nothing earth shattering here but I found it useful and cleans up my code a litle bit.

  • A Closer Look at AllowUnsafeUpdates

    The SPWeb.AllowUnsafeUpdates property recently came up in my project this week. I got the following exception:

    System.Exception: Microsoft.SharePoint.SPException: The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again. —> System.Runtime.InteropServices.COMException (0×8102006D): The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again.

    One of my team members told me to just set AllowUnsafeUpdates to true. I did and the exception went away. A quick google search shows dozens of blog posts and forum answers that the solution to the above exception is to set AllowUnsafeUpdates to true. After meeting a deadline I decided to go back and look at this property because it seems like a property that you would not want to set to true. The idea behind AllowUnsafeUpdates is to protect you from cross-site scripting attacks. All SharePoint does is check to see if HttpContext.Current is not null, and if it's not (this is in the context of a web request) it checks to see if the current web request is an HTTP GET (you clicked on a link) vs an HTTP post (you clicked on a button), and if it's not an HTTP POST (e.g., not a postback) it then checks the value of AllowUnsafeUpdates (which is false by default), if it is false then the security exception mentioned above is throw. I should mention I am leaving out a few steps to simplify the explanation. For more details of how the property is implemented see the MSDN documentation.

    There are two reasons you get the above exception and may be tempted to set AllowUnsafeUpdates to true to avoid it. The first is if you are trying to perform an update of a web or list when the page loads instead of during a postback. For example creating a delete.aspx page and passing the list item ID in as a query string parameter then performing the delete on that item. This will throw a security exception by default. But MSFT gave you the option to override this exception by setting AllowUnsafeUpdates to true. Do not do this. There is a reason you are getting an exception here. You are opening a risk that anyone can call that page and pass in any id in the querystring and delete a list item. Plus your search crawler or an outside search engine might accidentally hit that page and delete the list item. But for me I was not doing this. I had a button click event that was calling my SharePoint update code. The reason I was getting the exception was because we did not have the forms digest security control in the master page. This control validates the Web application when it attempts to access the Windows SharePoint Services APIs. So adding the following control to our master page removed 95% of our need for setting AllowUnsafeUpdates to true:

    <!-- Form Digest Security Control -->

    <asp:ContentPlaceHolder id="PlaceHolderFormDigest" runat="server">

        <SharePoint:FormDigest runat=server/>

    </asp:ContentPlaceHolder>

     

     

    The majority of the time you should have AllowUnsafeUpdates set to false. But there are always exceptions to the rule. The first that comes to mind is feature receivers. I haven't dug into this too much but it seems you have to set AllowUnsafeUpdates to true. If anyone can confirm or deny this please post in the comments. The other situation that comes to mind is one-off updates. For example, creating a console app that updates a particular column in a list is not a big enough security risk to worry about.

     

    Some Additional References:

    http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spsite.allowunsafeupdates.aspx

    http://hristopavlov.wordpress.com/2008/05/16/what-you-need-to-know-about-allowunsafeupdates/

    http://hristopavlov.wordpress.com/2008/05/21/what-you-need-to-know-about-allowunsafeupdates-part-2/

     

     

  • Setting the People/Group Field Type to a SharePoint Group

    I ran across this today and thought I would take a minute to blog about it because I didn't find exactly what I wanted by Googling. I have a SharePoint Group that I have created and I need to set that in a list so I can use it later on. I found a lot of articles on how to set a People or Group field by using the SPFieldUserValue but I didn't know how to get from a SPGroup to that object. Then it dawned on me to use the ID and Name properties of the group. Bam works like a charm. Here is the code:

     

     

    SPGroup group = rootWeb.SiteGroups[groupName];

     

    SPFieldUserValue value = new SPFieldUserValue(rootWeb,group.ID, group.Name);

    item["Committee Group"] = value;

  • Using Extension Methods to Make SharePoint More Palatable

    On my current project I have been using a lot of extension methods to hide things I don't like about the SharePoint API. For one I hate that the only way to determine if something is in a list, web, or group is by trying to access the item and then catch the exception. Yuck. Here is an extension method I wrote to test if a group exists in a site or not.

     

    public static bool Contains(this SPGroupCollection groups, string groupName)

    {

    try

    {

    SPGroup group = groups[groupName];

    return true;

    }

    catch (Exception)

    {

     

    return false;

    }

    }

     

    And here is how I use the extension method.

     

    if (!committeesRootWeb.SiteGroups.Contains(groupName))

    {

    committeesRootWeb.SiteGroups.Add(groupName, member, user, groupName);

    }

     

    For a little more info check out this post:

    http://johnholliday.net/post/2008/10/22/Streamline-Your-SharePoint-Code-Using-Extension-Methods.aspx

  • Infusion's Falcon Eye for Surface goes to the Superbowl

    This came through internally on Friday from fellow Infusionite Kartik Subramani. Congrats to everyone involved!

    About three weeks ago, Infusion was asked to produce a demo of a security application for managing security at SuperBowl XLIII in Tampa Bay this Sunday.  Although originally intended as a demo to gain some press for both Infusion and E-Sponder (the solution that Tampa Police uses in their day to day operations), it was such a hit, that the Incident Commander requested that it be brought into the Joint Operation Center, where every security organization from the local police to the [deleted in case this would get anyone in trouble.] were gathered to monitor the event.  The app allowed for real time visualization of incidents as they were reported to 911 and filed by police officers.  While I was down there, everything from loose dogs and lost children, to grand theft auto and bomb sweeps were showing up on the map.  In addition to having all that information at his fingertips, the Incident Commander was also able to listen to and speak out on to their various radio networks from the Surface [unit].

    You can read full details at the following links:

    http://www.microsoft.com/industry/government/news/e_sponder_super_bowl.mspx
    http://www.engadget.com/2009/01/29/microsoft-surface-being-used-to-coordinate-super-bowl-security/

    There were film crews from NBC and CBS filming the Incident Commander using the application.  I believe the NBC clip was to air this morning [Friday, Jan 30] on the Today Show, or the morning news, but I'm not sure when the CBS clip is going to air.

    Big shout out to Lan Nguyen, for his help with developing the application, and to Alex Preston and Trevor Hunter for their guidance during the architecture and design phase.

    And while everyone inside Infusion knows that Kurt Guenther is the "godfather of Falcon Eye," now you know too.If you have want to learn more about Surface or have questions about how we did it, you can reach Kartik and the team through the alias: surface@infusion.com.

       

    Read more about Falcon Eye at the Superbowl

    Read more about Falcon Eye and Surface

    Read more about Surface Development at Infusion

  • Disable a Button When the User Clicks It

    A common solution that I had to implement recently is users on a client's site were double clicking buttons and causing issues. In addition to causing issues users weren't sure if the site was working correctly on long running processes. The JavaScript code I wrote to solve this problem can be divided into two segments. One part handles buttons that make asynchronous calls and another part that handles buttons that cause post-backs. For the buttons that cause post-backs we loop through all buttons and assign the CanSubmitFunction as the click event for that button. In the CanSubmitFunction we keep track of if the user has clicked the button before and if they have we display an alert and prevent the button from submitting. I should mention that I originally tried to disable the button. But doing this prevents the button from submitting and trying to force a submit is difficult to say the least.

     

    // wire up the disable click event

    var buttonControls = document.getElementsByTagName("input");

    for (i = 0; i < buttonControls.length; i++) {

    // if this input type is button, disable

    if (buttonControls[i].type == "submit") {

    addClickEvent(buttonControls[i], CanSubmitForm);

    }

    }

     

    function addClickEvent(obj, fn) {

    if (obj.addEventListener) {

    obj.addEventListener('click', fn, false);

    } else if (obj.attachEvent) {

    obj.attachEvent('onclick', fn);

    }

     

    }

     

    var isSubmitted = false;

    function CanSubmitForm() {

    var canSubmit = false;

    if (!isSubmitted) {

    isSubmitted = true;

    canSubmit = true;

    }

    else {

    alert("Please wait for page to load before making another selection.");

    }

    return canSubmit;

    }

     

    For buttons that makes asynchronous calls we can disable the button. In addition to disabling the button we change the cursor so it shows the hourglass. I think the code below is pretty self-explanatory. One issue I do have with this solution is having to different types of behaviors on the buttons throughout the site. I may change the asynchronous code show it also displays an alert when the user clicks on the button twice.

    // wire the callbacks for the Ajax events

    var prm = Sys.WebForms.PageRequestManager.getInstance();

    prm.add_initializeRequest(InitializeRequest);

    prm.add_endRequest(EndRequest);

    //--------------------------------------

     

    function InitializeRequest(sender, args) {

    document.body.style.cursor = "wait";

    var buttonControls = document.getElementsByTagName("input");

     

    for (i = 0; i < buttonControls.length; i++) {

    // if this input type is button, disable

    if (buttonControls[i].type == "submit") {

    buttonControls[i].disabled = true;

    }

    }

    }

     

    function EndRequest(sender, args) {

    document.body.style.cursor = "default";

    var buttonControls = document.getElementsByTagName("input");

     

    for (i = 0; i < buttonControls.length; i++) {

    // if this input type is button, enable

    if (buttonControls[i].type == "submit") {

    buttonControls[i].disabled = false;

    }

    }

    }

     

    The solution is deployed to an existing SharePoint site so it needed to work for all buttons instead of specifying each button by name. You can see above I made use of the unobtrusive JavaScript pattern to make this possible. We also need to put this code in a JavaScript file and add it to the master page that the SharePoint site is using. One more thing to note is I had the JavaScript file reference just above the closing tag to ensure that all the DOM elements have been loaded before the JavaScript code executes.

    *Warning - This has not been tested in Firefox. This was a closed intranet and not a requirement for this solution. Though I doubt it would take long to make this code cross-browser compatible.

     

  • Searching Boolean Values in SharePoint

    By no means am I an expert in Search but I did want to make a note of one thing. A Boolean is represented by yes/no in a SharePoint list but in your search query string you should use true/false as the value. For example I had a published field that I wanted to append to the query string based on certain user selections. So I added "Published:true" via code. If you say add "Published:1" you will get the following error: "Your search cannot be completed because of a service error. Try your search again or contact your administrator for more information".

    One final thing when you are mapping your properties be sure and select the type before clicking "Add Mapping". It isn't obvious at first but SharePoint is filtering the results based on the type.

More Posts « Previous page - Next page »
2012 dotnetmafia.
Powered by Community Server (Non-Commercial Edition), by Telligent Systems