Feb 09 2012

Clearing the Value of an AudienceEditor Control during Postbacks

Category: ASP.NET, SharePoint, TechnologyAdam Toth @ 6:36 pm

I was recently working on an administrative page for Central Administration, and had the need to use an AudienceEditor control in a form, and more difficult yet, use it inside an AJAX UpdatePanel. The AudienceEditor is the control that is used to enable a user to pick audiences, such as on the Target Audience field in the Advanced section of a Web Part’s Tool Pane.

image

As the picture shows, this form has a TreeView on the left, and a Panel on the right, and depending on what node in the TreeView is selected, the panel on the right needs to refresh and reload the audience information into the AudienceEditor control. Setting the value in the AudienceEditor via C# is easy, just set the .Text property. Everything works fine when you are setting this value once (e.g. PageLoad), but if you have to set this value on subsequent postbacks, you’ll find that the control keeps the first submitted value, and displays that same value after every postback. You’ll also find that if you use this control in an UpdatePanel, and the control isn’t Visible on initial page load, then the control will not work.

To make this work, first thing is make sure the control is not in a Panel or PlaceHolder that is not visible on initial PageLoad (Visible=false). If you need to hide the control in the beginning, then use CSS display:none, and toggle visibility between PostBacks by Toggling the CssClass of the container control.

Next, the control emits several hidden fields, divs, textareas, and javascript variables into the page. If you want the control to display a new value after postback, you’ll have to clear out these elements on the client side just before postback. This will reset the control, and enable it to take a new value and display that new value after the postback.

Following is the function I wrote to clear out the AudienceEditor. Call this on an OnClientClick event of a button or some similar hook on the control that will be initiating the postback (in my case it was the onNodeClicking client-side event of the Telerik RadTreeView control).

        function clearAudienceEditor() {

            if (typeof(currentEntityEditorXml) != "undefined") {
                currentEntityEditorXml = '';
            }

            var downLevelTextBox = document.getElementById('<%= audienceEditor.ClientID + "_downLevelTextBox" %>');
            var upLevelDiv = document.getElementById('<%= audienceEditor.ClientID + "_upLevelDiv" %>');
            var hiddenSpanData = document.getElementById('<%= audienceEditor.ClientID + "_hiddenSpanData" %>');

            if (downLevelTextBox != null) {
                downLevelTextBox.value = '';
            }
            if (upLevelDiv != null) {
                upLevelDiv.innerHTML = '';
            }
            if (hiddenSpanData != null) {
                hiddenSpanData.value = "&#160;";
            }

        }

Tags: ,


Dec 03 2010

Gotchas Registering a Company for a Windows Phone 7 Marketplace Account

Category: Technology, WP7Adam Toth @ 5:31 pm

Registering my company for a Windows Phone 7 App Hub Marketplace account was not an easy or obvious process. One of the big problems is the use of Windows Live ID as the authentication mechanism. Live ID is a system designed for individual users, which in the App Hub is being unrealistically stretched to apply to companies as well.

Here are the steps I took, and some mistakes I made during the process. Hopefully you can spare yourself from wasting precious minutes of your life like I did.

Step 1 – Create a Generic Windows Live ID

Any company that signs up for a service wants to be able to use a generic account to login with. People change jobs all the time, and you don’t want that account locked out or inaccessible because someone left the company, or their personal email address doesn’t work anymore.

My first step was to create a generic Windows Live ID account for Blue Rooster Inc. I started at the App Hub membership site and clicked the link to Join Now:

image

Then I clicked the link to Sign Up Now:

image

Next, I chose the option that says "Yes, use my email address".

image

At this point, I already had a generic company email alias working (something like apphub@mycompany.com), so I entered that and filled in the other information. Make sure to test this email address first, because otherwise you’ll be stuck if it can’t receive mail.

image

GOTCHA #1: The secret question options are all geared towards personal pieces of data. The only generic one I could use was Favorite Historical Person. I chose someone that made sense for our company, and wrote it down, along with the password.

GOTCHA #2: If you wait too long on this screen, it’ll kick you back to the previous screen.

GOTCHA #3: The CAPTCHA is hard to read. Took me a couple times to get it right.

image

Next I entered my profile data. Since this was a generic account, many of the fields on here were not applicable (Gender, Marital status, etc.). I entered what I thought was best. For birthdate, the company was founded in 2004, so I just put January 1 2004 as the birthdate.

WRONG!!!

GOTCHA #4 MAJOR!Make sure your Birthdate is a valid legal age!

By specifying 2004 as the birth year, the Live ID system thought I was a minor, and wouldn’t let me proceed unless I got a parent to approve this and validate their own identity via credit card. This was a DEAD END, and I had to cancel this account and start over.

image

Next, I validated my email address.

imageimage

Then I had to check my email address and validate the account by clicking the link in the email.

image

GOTHCA #5: This will open a new browser window. You will not be taken back to the App Hub after this (it takes you to www.msn.com), and will have to navigate back yourself.

image

Step 2 – Really Register at the Marketplace

Once you have your generic Live ID working, you can go back to the App Hub and start over. This time I signed in with my new Live ID. I filled out my country, selected Company as the account type, and accepted the terms of use:

image

On the next screen, I really screwed up, but didn’t know it for a while. When you enter your account details, there are two sections, Personal Details, and Company Details. I didn’t want to enter myself or another personal contact in the Personal Details section, as I didn’t know if that would show up in the marketplace when someone viewed one of our applications. I wanted the profile to be generic as well, so I entered "Blue" for the first name, "Rooster" for the last name, and used the Windows Live ID generic email as the email address.

image

Notice the arrow pointing to the message regarding the email address. I figured I was totally fine here, since my generic account can receive email successfully. Also, there is an Approver section at the bottom of the Company Details section that looked like the right place to put my own personal information.

WRONG!!!

GOTCHA #6: If you put generic information in the Personal Details section, GeoTrust will not be able to verify your identity.

Of course they won’t tell you this, and your account will be pending Tax ID Verification indefinitely, and you won’t be able to developer unlock your phone until someone gets back to you. I had to log a support ticket and harass until someone finally emailed me that my account was still pending because of this. I got an email from GeoTrust shortly after, which had a link to a Live Chat session. A gentleman at GeoTrust took my order ID, and changed my contact information, and a couple hours later my marketplace account was fully verified. This whole thing delayed me an entire week.

After this step, you are directed to fill out your profile. This is where you choose your XBox Live Gamer tag (another thing that really does not make sense if you are a generic company account), and setup some default information.

GOTCHA #7: I had a hard time finding a non-used XBox Live gamer tag. I tried "Blue Rooster", "BlueRooster", "Blue Rooster Marketing", and finally had to settle for "Blue Rooster, Inc.".

Unfortunately I’m missing screen shots of the next steps in the process, but I’ll note the process and some gotchas that I can remember.

After filling out the profile details, it was time to provide payment.

GOTCHA #8: The payment system had a hard time with a corporate AMEX card. It was really finicky about the Suite number in the address.

GOTCHA #9: If you want a receipt of the purchase, print the screen that shows the amount. There is no place in the marketplace afterwards to get a receipt, or to view the transaction.

Once you are done with the payment process, you’ll be taken to your App Hub dashboard. You’ll also soon get an email from GeoTrust. If you’ve done this right (and didn’t run into GOTCHA #6), then your email will contain contact information for an individual, not for a generic company account.

*** NOTE: This email was automatically generated from an unmonitored mailbox. ***

 

Dear Approver:

 

The person identified below requested a Microsoft Windows Phone Marketplace developer account on behalf of Blue Rooster. GeoTrust, a Microsoft partner, needs more details to complete Marketplace registration. 

 

Applicant information:

 

  Name:   Blue Rooster

  Email:  xxx@xxx.com

  Phone:  xxxxxxxxxx

 

Successful Marketplace registration generates a code signing certificate that will identify Blue Rooster as the responsible publisher.

 

Blue Rooster identified you as someone who can authorize this request on behalf of Blue Rooster.  If you do not have this capability, then please notify Blue Rooster, then access the URL below and click "I Do Not Approve". 

 

***Note that canceling this account will require the requesting individual to create a new Marketplace account using a different Windows Live ID and pay an additional registration fee.*** 

 

Please follow the URL below to approve or not approve this request:

 

     https://products.geotrust.com/orders/Approval.do?pin=xxxxxxxxxxxx

 

If you have any questions, please consult the requestor, Blue Rooster, or contact GeoTrust Customer Support at:

 

     https://knowledge.geotrust.com/support/knowledge-base/index?page=content&id=SO14669&actp=search&viewlocale=en_US

 

Thank you.

 

GeoTrust Customer Support

http://www.geotrust.com/support

Hours of Operation: Mon - Fri 05:00 - 17:00 (PST)

Email:     cs-orders@geotrust.com

Web:       http://www.geotrust.com

Phone:     1-866-436-8787 or 1-678-366-8399 option 2

Live Chat: http://www.geotrust.com/support

 

 

After clicking the link, you’ll be taken to a simple page that basically lets you Accept or Cancel the verification process. After finishing this, you can finally breathe a sigh of relief and wait for the verification process to complete.

WRONG!!!

GOTCHA #10: You MUST navigate to the PAYEE DETAILS screen in the App Hub Dashboard, and fill in your bank account and Tax ID information in order to have your tax ID and identity validated. The process never took me there on its own, and there was no email or other communication that told me that I needed to do this.

That’s pretty much it, and much harder than I think it needed to be.

Tags: , ,


Nov 15 2010

Fixing WordPress and Windows LiveWriter xmlrpc errors

Category: TechnologyAdam Toth @ 2:48 pm

I recently had my blog moved to a different server at my web host, and after the move, I couldn’t connect Windows LiveWriter with my blog anymore. I would get an error "Invalid Server Reponse – The response to the blogger.getUserBlogs method received from the blog server was invalid." I found this post which was exactly my problem:

http://coding-paparazzi.sylvainlafontaine.com/2010/02/solving-connection-problems-wlw.html

I was able to fix it by editing my wp-config.php in notepad and saving with ANSI encoding instead of UTF-8 and re-uploading to my site. That stripped out the byte order mark at the beginning, and fixed my connection issues.

Tags: ,


Nov 15 2010

2010 Riesling

Category: Family, Life, WineAdam Toth @ 1:01 pm

We are making Riesling this year. There were a bunch of grapes still left on the vines, and it was just too tempting to pick them. The bunches came off easily – we didn’t need clippers, just a good tug.

So I don’t forget it, here are the details about our 2010 Riesling:

  • Picked on 11/13/10.
  • 17 crates, about 30 pounds/crate.
  • Crushed on 11/13/10 late afternoon.
  • Pressed on 11/14/10 late morning.
  • Yield – 25 gallons

Some additional info on sugar content:

Started out with Brix of 20,
Added 10 cups of corn sugar which brought the brix up to 22
Added 20 teaspoons of Yeast Nutrient
and the starter yeast was Lalvin, kv1-1116 a good all around white wine yeast. 

Tags: ,


Nov 02 2010

Creating a Custom Welcome Menu for SharePoint Server 2010 – Part 3

Category: ASP.NET, SharePoint, TechnologyAdam Toth @ 4:20 pm

Part 3 – Sign Out/Sign in as a Different User

A project I am working on called for a custom implementation of the SharePoint Welcome menu control. The replacement control needed to provide the following:

  • Implement the look and behaviors that the designers created.
  • Exclude some default SharePoint menu items (such as My Regional Settings).
  • Reuse some existing SharePoint menu items (such as Sign Out/Sign in as a Different User).
  • Allow for the addition of other custom menu items in the future.
  • Display thumbnail of the user’s profile picture.

I had to create a control that looked and behaved like the following:

CropperCapture2_thumb1_thumb

The designers came up with some clean, semantic markup married with some jquery, for me to start from:

<div class="header">

    <img class="header-logo" src="/images/header_logo.png" alt="" width="169" height="78" />

    <div class="header-bar">

        <div class="profile_menu">

            <a href="#" class="profile_btn">

                <span class="image"><img src="" style="width:20px;height:20px" /></span>

                <span class="name">John Doe</span>

                <span class="arrow"></span>

            </a>

            <div class="profile_dropdown">

                <div class="dropdown_bkgrd">

                    <ul>

                        <li>Edit Profile</li> 

                        <li>My Site</li>

                        <li>Log Out</li>                        

                        <li>Sign in as a Different User</li>

                    </ul>

                </div>

            </div>

        </div>

    </div>

</div>

This is part 3 of a three part series.

  1. Part 1 – Overview, Profile Picture, and User Name
  2. Part 2 – Edit Profile and My Site links
  3. Part 3 – Sign Out/Sign in as a Different User

Continue reading “Creating a Custom Welcome Menu for SharePoint Server 2010 – Part 3″

Tags: , ,


Nov 02 2010

Creating a Custom Welcome Menu for SharePoint Server 2010 – Part 2

Category: ASP.NET, SharePoint, TechnologyAdam Toth @ 4:10 pm

Part 2 – Edit Profile and My Site links

A project I am working on called for a custom implementation of the SharePoint Welcome menu control. The replacement control needed to provide the following:

  • Implement the look and behaviors that the designers created.
  • Exclude some default SharePoint menu items (such as My Regional Settings).
  • Reuse some existing SharePoint menu items (such as Sign Out/Sign in as a Different User).
  • Allow for the addition of other custom menu items in the future.
  • Display thumbnail of the user’s profile picture.

I had to create a control that looked and behaved like the following:

CropperCapture2_thumb1

The designers came up with some clean, semantic markup married with some jquery, for me to start from:

<div class="header">

    <img class="header-logo" src="/images/header_logo.png" alt="" width="169" height="78" />

    <div class="header-bar">

        <div class="profile_menu">

            <a href="#" class="profile_btn">

                <span class="image"><img src="" style="width:20px;height:20px" /></span>

                <span class="name">John Doe</span>

                <span class="arrow"></span>

            </a>

            <div class="profile_dropdown">

                <div class="dropdown_bkgrd">

                    <ul>

                        <li>Edit Profile</li>

                        <li>My Site</li>

                        <li>Log Out</li>

                        <li>Sign in as a Different User</li>

                    </ul>

                </div>

            </div>

        </div>

    </div>

</div>

This is part 2 of a three part series.

  1. Part 1 – Overview, Profile Picture, and User Name
  2. Part 2 – Edit Profile and My Site links
  3. Part 3 – Sign Out/Sign in as a Different User

Continue reading “Creating a Custom Welcome Menu for SharePoint Server 2010 – Part 2″

Tags: , ,


Nov 02 2010

Creating a Custom Welcome Menu for SharePoint Server 2010 – Part 1

Category: ASP.NET, SharePoint, TechnologyAdam Toth @ 4:00 pm

Part 1 – Overview, Profile Picture, and User Name

A project I am working on called for a custom implementation of the SharePoint Welcome menu control. The replacement control needed to provide the following:

  • Implement the look and behaviors that the designers created.
  • Exclude some default SharePoint menu items (such as My Regional Settings).
  • Reuse some existing SharePoint menu items (such as Sign Out/Sign in as a Different User).
  • Allow for the addition of other custom menu items in the future.
  • Display thumbnail of the user’s profile picture.

I had to create a control that looked and behaved like the following:

CropperCapture[2]

The designers came up with some clean, semantic markup married with some jquery, for me to start from:

<div class="header">

    <img class="header-logo" src="/images/header_logo.png" alt="" width="169" height="78" />

    <div class="header-bar">

        <div class="profile_menu">

            <a href="#" class="profile_btn">

                <span class="image"><img src="" style="width:20px;height:20px" /></span>

                <span class="name">John Doe</span>

                <span class="arrow"></span>

            </a>

            <div class="profile_dropdown">

                <div class="dropdown_bkgrd">

                    <ul>

                        <li>Edit Profile</li> 

                        <li>My Site</li>

                        <li>Log Out</li>                        

                        <li>Sign in as a Different User</li>

                    </ul>

                </div>

            </div>

        </div>

    </div>

</div>

This is part 1 of a three part series.

  1. Part 1 – Overview, Profile Picture, and User Name
  2. Part 2 – Edit Profile and My Site links
  3. Part 3 – Sign Out/Sign in as a Different User

Continue reading “Creating a Custom Welcome Menu for SharePoint Server 2010 – Part 1″

Tags: , ,


Oct 15 2010

Adding and Deploying Generic Handlers (.ashx) to a SharePoint 2010 Visual Studio Project

Category: ASP.NET, SharePoint, TechnologyAdam Toth @ 2:00 pm

Generic Handlers (.ashx files) deployed to the _layouts directory are not directly supported by Visual Studio 2010 SharePoint projects like custom .aspx application pages are.

If you try to Add New Item… and select the Web or SharePoint categories in a VS 2010 SharePoint project, you won’t find Generic Handler anywhere.

image

You’ll find ASP.NET Handler, but this will require you to create entries in web.config to make your handler work. In order to add a new .ASHX generic handler and get it to deploy properly, you can use the following steps:

  • Right-click the project, and select Add New Item…
  • Choose the Application Page template.
  • In the name box, enter a name for your file, with an .ashx extension.
    image
  • Open the .ashx file, delete the contents and replace with the following, changing your Class= attribute with your desired namespace and class name:
    <%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>

    <%@ Assembly Name="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

    <%@ WebHandler Language="C#" Class="MyNamespace.MyGenericHandler" %>

    Note: If you want to reference other SharePoint assemblies in your code-behind, you will need to add an @ Assembly directive for each DLL.

  • Open the ashx.cs file.
    • Add a using statement for System.Web.
    • You probably don’t need the using statement for Microsoft.SharePoint.WebControls, so remove it.
    • Change your namespace if necessary.
    • Change the class to inherit from IHttpHandler.
    • Implement the IHttpHandler interface. Your code should now look something like this:
      using System;

      using Microsoft.SharePoint;

      using System.Web;

       

      namespace MyNamespace

      {

          public partial class MyGenericHandler : IHttpHandler

          {

       

              #region IHttpHandler Members

       

              public bool IsReusable

              {

                  get { throw new NotImplementedException(); }

              }

       

              public void ProcessRequest(HttpContext context)

              {

                  throw new NotImplementedException();

              }

       

              #endregion

          }

      }

  • In the Solution Explorer, delete the ashx.designer.cs file, it is not needed.
  • In the Solution Explorer, click the .ashx file, and in the Properties pane, set the Build Action to Content.
  • In the Solution Explorer, click the .ashx.cs file, and in the Properties pane, set the Build Action to Compile.
  • Make sure to enable Token replacement for .ashx extensions. This will replace the $SharePoint.Project.AssemblyFullName$ token with the full strong name of your assembly, enabling you to reference other classes in your compiled assembly from the ashx code-behind.You can read more about token replacement here. To enable this for your Project, Unload your Project, Edit the .csproj file and add the following text to a PropertyGroup, and Reload your project:
    <PropertyGroup>

      <TokenReplacementFileExtensions>ashx</TokenReplacementFileExtensions>

    </PropertyGroup>

Tags: , , ,


May 27 2010

Creating a Custom Metadata Editor Plugin for Colligo for SharePoint

Category: SharePoint, TechnologyAdam Toth @ 2:07 pm

Just wrapped up a project developing a custom metadata editor to plugin to the Colligo Contributor for SharePoint client.

If you aren’t familiar with Colligo, it’s a desktop client application/outlook add-in/explorer file manager, that enables users to save documents or emails directly to SharePoint, and be prompted for metadata at the time of saving.

Colligo reads the content type of the target lists/libraries, and generates a default form very similar to what SharePoint does with the default EditForm.aspx ListForm web part. If you don’t like the default form, or need to customize the metadata entry experience (for example custom validation, pulling from external data sources, inter-dependent controls), you can develop a custom editor and show your own Windows Forms-based form to the user.

Colligo default editor form
The default Colligo Editor form, shown here when adding a new Announcement.

How to Start

To start developing a custom editor, begin by installing Colligo Contributor, and obtaining your product and sdk keys from Colligo.

Create a new Visual Studio Class Library project, and add a reference to the Colligo dlls in the GAC.

Add the necessary using statements:

using Colligo;

using Colligo.Properties;

using Colligo.Util;

using Colligo.WML.MetaData;

Change your class to inherit from the ICustomEditor class:

namespace MyNamespace

{

    public class MyCustomEditor : ICustomEditor

    {

 

    }

}

Implement the Interface methods:

namespace MyNamespace

{

    public class MyCustomEditor : ICustomEditor

    {

 

        // SDK Key

        private const string SDK_KEY = "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX";

 

        #region ICustomEditor Members

 

        public string GetSdkKey()

        {

            return SDK_KEY;

        }

 

        public EditorResult ShowEditor(IEditContext context)

        {

            // Show your form here

 

        }

 

        public ResolveConflictResult ShowResolveConflictDialog(IResolveConflictContext context)

        {

            return ResolveConflictResult.UseDefaultResolveDialog;

        }

 

        #endregion

 

    }

}

In the ShowEditor method, this is where you can create an instance of a Windows Form, and call the ShowDialog method on it. You can also pre-validate and avoid showing your form for situations that are not appropriate.

public EditorResult ShowEditor(IEditContext context)

{

 

    // Check if this is something we care about

    if (!context.List.IsDocumentLibrary)

    {

        return EditorResult.UseDefaultEditor;

    }

    if (!string.Equals(context.List.Name, "Private Documents", StringComparison.CurrentCultureIgnoreCase) &&

        !string.Equals(context.List.Name, "Public Documents", StringComparison.CurrentCultureIgnoreCase))

    {

        return EditorResult.UseDefaultEditor;

    }

 

    // Only show for Create/Edit (use the default Colligo form for Viewing)

    if (context.EditorMode == EditorMode.Create || context.EditorMode == EditorMode.Edit)

    {

        using (myCustomWindowsForm myForm = new myCustomWindowsForm(context))

        {

            DialogResult createResult = DialogResult.None;

 

            createResult = myForm.ShowDialog(context.Parent);

 

            switch (createResult)

            {

                case DialogResult.Cancel:

                    return EditorResult.Cancel;

                case DialogResult.OK:

                    return EditorResult.OK;

                case DialogResult.No:

                    return EditorResult.UseDefaultEditor;

            }

        }

    }

    else

    {

        // View - Show the default editor

        return EditorResult.UseDefaultEditor;

    }

 

    // Fall through

    return EditorResult.OK;

 

}

Notice I am passing in the IEditContext instance into my form’s constructor. The IEditContext object has all the goodies in it, and will give you access to the list, the web, the content types, list item metadata, etc.).

What to Consider

Some basic things to consider are:

  • Which scenarios will your editor cover? View, Create, Edit?
  • Is this only for documents, or list items, or both?
  • Will you support content types? A list/library can be configured with multiple content types, which you will need to create a UI for selecting/changing if you decide to support that.
  • How will you handle multiple files? Will you enable setting different data for each item, or will you force all items to use the same entered metadata? Think carefully about the “Name” field for documents in document libraries. You want to make sure that the same name is not used for multiple documents.
  • Will you allow changing folders (for document libraries with folders enabled)? If so, you’ll need to build this UI.

There are a number of ways/methods that may kick off the display of your form, and you need to consider each of these:

  • User selects New > Item from within Colligo Contributor
    • This is similar to the New > [Content Type] menu directly in SharePoint. You can expect that EditorContext.ContentType and EditorContext.ListItems[0].ContentType will not be null.
  • User selects Upload from within Colligo Contributor
    • This is similar to Upload Document from within SharePoint. EditorContext.ContentType and EditorContext.ListItems[0].ContentType may be null.
  • User drags/drops a single file onto Colligo Contributor
    • EditorContext.ContentType and EditorContext.ListItems[0].ContentType may be null.
  • User drags/drops multiple files onto Colligo Contributor
    • EditorContext.ContentType and EditorContext.ListItems[0].ContentType may be null.
  • User performs a single File > Save As from within an application
    • EditorContext.ContentType and EditorContext.ListItems[0].ContentType may be null.
  • User drags/drops multiple files onto the Colligo area in Windows Explorer
    • EditorContext.ContentType and EditorContext.ListItems[0].ContentType may be null.
  • User selects Edit Properties from within Colligo Contributor
    • Need to grab existing values and prepopulate your controls. EditorContext.ContentType and EditorContext.ListItems[0].ContentType will not be null.


Some Gotchas

Following are some gotchas to be aware of:

Check for Null

Don’t make any assumptions about any of the items in the IEditContext object. ContentTypes may be null, Fields may not exist or be null, other relevant ILists in the Web may not be synchronized locally, and will be null, etc., etc., etc. Check everything for null first, and test everything that returns a collection/array for Count and Length > 0. If there are fields/lists/lookup column values that your form expects, check for the existence of these things right away, and exit if you don’t find them.

Parent Windows

If your form is called via the Save As dialog from an application (or via the FileManager), the ParentWindow handle may not be valid, so be careful with the ShowDialog(IWin32Window) overload, which threw a System.ComponentModel.Win32Exception for me. I had to wrap my ShowDialog(context.Parent) in a try>catch, and then try it without any parameters (ShowDialog() ).

Custom Field Types

If you are using any custom field types, be really careful to make sure and store the data in the proper format. My customer was using a couple of custom field types found on CodePlex, and one of them extended the Lookup field, and it took me a few traces with Fiddler to figure out that it wanted its values in lookup column format (“52;#ItemName”);

Site Lookup Columns

If you have any lookup columns that are defined in higher-level sites, and you are using those site columns in lists located in subsites, then Colligo will not be able to see the lookup values. In order to implement these scenarios, you will have to force your users to synchronize the higher level sites as well as the subsites.

Tags: ,


May 26 2010

Filtering XML output of SPListItemCollection using Linq to XML

Category: SharePoint, TechnologyAdam Toth @ 1:57 pm

I’ve been writing a slurry of code to return list item XML so that it can be parsed and consumed by AJAX components on the client side. Since Lists.asmx does not work in anonymous access scenarios, I’ve been creating many proxy .ashx Http Handlers installed in the LAYOUTS directory, to query via the object model and return the XML of the list items, using the .Xml property of a SPListItemCollection.

I had one particular scenario where I couldn’t pre-filter the items in the collection with an SPQuery object (too complicated a query for CAML), so I needed a way to filter the SPListItemCollection afterwards using C#, before returning the XML.

The SPListItemCollection offers the .Delete() and .DeleteItemById() methods, however they will commit the deletion back to SharePoint. I wanted to simply remove some items from the in-memory collection, not delete the items from the server. There was no way that I could see to remove items from an SPListItemCollection in memory only.

I looked into sub-classing or extending the SPListItemCollection class, but there is no public constructor in the base class, and no way to get at the logic behind the .Xml property without nasty reflection.

I ultimately ended up resorting to using Linq to XML to delete the rows directly from the returned XML, and then adjusted the ItemCount accordingly.

Here’s the code:

// Get the list items from a list

SPListItemCollection items = myList.GetItems(mySPQuery);


// Get the xml of the list items

itemXml = surveyItems.Xml;


XNamespace z = "#RowsetSchema";

XDocument xdoc = XDocument.Parse(itemXml);


IEnumerable<XElement> rows = xdoc.Root.Descendants(z + "row");

List<XElement> rowsToDelete = new List<XElement>();


foreach (XElement row in rows)

{

    // Here is where you can test for a condition, and decide to remove a row

    if (row.Attribute("ows_Title").Value.Contains("Some string to filter on"))

    {

        rowsToDelete.Add(row);

    }

}


while (rowsToDelete.Count > 0)

{

    // Update the parent row count

    int rowCount = Convert.ToInt32(rowsToDelete[0].Parent.Attribute("ItemCount").Value);

    rowsToDelete[0].Parent.Attribute("ItemCount").Value = (rowCount - 1).ToString();

    rowsToDelete[0].Remove();

    rowsToDelete.RemoveAt(0);

}


// Get the newly filtered xml

itemXml = xdoc.ToString()

Tags: , , , ,


Next Page »