This morning I was trying to add an OOTB lookup field to a custom list in a SharePoint sub website. I got an error of “Field type x is not installed properly. Go to the list settings page to delete this field.”

I looked through all my code and found no reference to the offending field the error was talking about. Only some random log file had info on me having used it months ago. This error didn’t happen in the root site, nor in other subweb sites. The first useful google I found was Paul Beck’s Blog . I really didn’t want to think about diving into messing with the SQL tables though. Instead I poked around in SharePoint Manager 2007(SPM) for a while looking for some explaination.

Although SPM is great for browsing–it’s like finding a needle in a haystack when looking for where a custom field type is in use. I ended up creating a Layouts page to search all the sitecollections fields to see where this offender was in use. Below is the layouts page code in case you ever need it.

If you need to decode the escaped html etc. you might use a escaped html decoder.


 <%@ Assembly Name="Microsoft.SharePoint.ApplicationPages, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>  
<%@ Page Language="C#" EnableViewState="false" EnableViewStateMac="false"   %> 
<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %> 
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
<%@ Import Namespace="Microsoft.SharePoint" %>

<%@ Register TagPrefix="wssuc" TagName="ToolBar" src="~/_controltemplates/ToolBar.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="ToolBarButton" src="~/_controltemplates/ToolBarButton.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="ViewHeader" src="~/_controltemplates/ViewHeader.ascx" %>
<%@ Register Tagprefix="wssawc" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<script runat="server">    
    protected void Page_Load(object sender, EventArgs e)
    {
        
    }
    protected void go(object sender, EventArgs args)
    {
        
        SPSite site = SPContext.Current.Site.RootWeb.Site;
        using (SPWeb web = site.OpenWeb("/"))
        {
            //process root lists
            foreach (SPList list in web.Lists)
            {
                processList(web, list);                
            }
            
            //process root fields
            if (fieldTypeInUse(web.Fields, txtFieldTypeString.Text))
            {
                litResults.Text += "Found in: " + web.Url.ToString() + " : SITE FIELDS<br><br>";
            }
            
            //process child webs
            if (web.Webs.Count > 0)
            {
                for (int i = 0; i < web.Webs.Count; i++)
                {
                    using (SPWeb subweb = web.Webs[i])
                    {
                        processWeb(subweb);
                    }
                }
            }
        }
    }
    
    protected void processWeb(SPWeb web)
    {

        //process root lists
        foreach (SPList list in web.Lists)
        {
            processList(web, list);
        }
        
        //process root fields
        if (fieldTypeInUse(web.Fields, txtFieldTypeString.Text))
        {
            litResults.Text += "Found in: " + web.Url.ToString() + " : SITE FIELDS<br><br>";
        }
        
        //process child webs
        if (web.Webs.Count > 0)
        {
            for (int i = 0; i < web.Webs.Count; i++)
            {
                using (SPWeb subweb = web.Webs[i])
                {
                    processWeb(subweb);
                }
            }
        }
    }
    protected void processList(SPWeb web, SPList list)
    {
        if (fieldTypeInUse(list.Fields, txtFieldTypeString.Text))
        {
            litResults.Text += "Found in: " + list.ParentWebUrl.ToString() + " : " + list.Title + "<br><br>";
        }
    }
    public static bool fieldTypeInUse(SPFieldCollection collection, string TypeAsString)
    {
        foreach (SPField field in collection)
        {
            if (field.TypeAsString == TypeAsString)
            {
                return true;
            }
        }
        return false;
    }
    

    
    
</script>
<html><head><title>Find Rouge Field Type</title></head>
<body>
    <form id="form1" runat="server"> 
    <br />
    <br />
               
        <strong>Find Rouge Field Type</strong><br />
        Fill the textbox with the name of the offending custom field. 
        Then click "Go" to search your entire site for any use of that field.
        If you are using this then you have probably gotten an error stating that 
        a field is not installed correctly or something to that effect. Use the name of the field 
        in the error message as the text for the textbox.<br /><br />
        <asp:TextBox ID="txtFieldTypeString" runat="server"></asp:TextBox>
        <asp:Button ID="GoButton" runat="server" OnClick="go" Text="GO" />
        <br /><br />
        <strong>Results</strong>
        <hr />
        <asp:Literal ID="litResults" runat="server"></asp:Literal>
        
    </form>
</body>
</html>

I have a project where a basic ASP.NET public web site drills into a private SharePoint web object model and produces most of the content for the public side. One area in particular presents many science projects that go on within the organization. Some folks want different options though as to how their projects are presented on the page–meaning they might want three columns instead of two or a different menu style, etc.

My first thought was that trying to do that and still use the same aspx page would mean having to create all the page controls etc. in code and then add them to the page. Possibly each different layout would have its own method block with all the code to do that. Can you imagine how messy that could get. Then if the pages had any kind of event associations etc. it would get even worse.

Then I considered the possibility of using the nested master page concept. Basically just turn my project.aspx?projID=xx into a masterpage director. So that when the project.aspx page loaded it would check what template was suppose to be associated with the project and then choose that one by assigning the correct master page.

In my Page_PreInit I would need to add code to check the SharePoint project list item based on the projectID querystring value and get the name of the template that was supposed to be associated with that project.
Then do something like the following:

string templateName = “TemplateNameFromSPProjectList”;
this.Page.MasterPageFile = “~/” + templateName + “.master”;

I’ll have to post back the results of taking this approach. If anyone knows of a better way of doing this let me know. And if there are any drawbacks that I don’t see in taking this route of operating mostly within a nested master page for page buildout let me know.

Usually I find it hard to make time to post anything about what I do on a regular basis. So out of many things going on, I figured I would post about a simple change or addition I made to some helper class methods I use pretty regularly in both asp.net and sharepoint programming. The biggest part of which is using the Type.InvokeMember() method of the .NET System namespace to make one method a little more generic.

My original need was to parse sharepoint rich text content fields for html image tags and remap the url to an asp.net image handler. At some point I’ll have to detail the whole image handler concept that I am talking about. For a simpler example, my most recent need was just to parse for any html anchor tags and make sure that a target=”_blank” attribute existed.  

This simple version is broken up into two methods. The first is just looking for the specific tag throughout the rich text. I found myself asking if there was a way to use the first method with any similar operation. Before realizing I could use InvokeMethod, I figured maybe a switch statement might work. If I took that route it meant adding case statements every time there was a new method for dealing with a certain tag or operation on a tag–kinda a pain. 


using System;
using System.Collections.Generic;
using System.Text;

public class Helpers
    {
        /// <summary>
        /// Use this method to do work on all specific tag instances in a string
        /// An example would be that you want to check that a target attribute exists in all anchor tags in the supplied string.
        /// DataStr would be the original string, tag would be "a" (it is case insensitive), and method would be ensureAtagBlankTarget.
        /// Notice ensureAtagBlankTarget is pretty specific and must be a method already in the Helpers class.
        /// </summary>
        /// <param name="DataStr">The original string</param>
        /// <param name="tag">The tag you want to work on</param>
        /// <param name="methodToRunOnTag">A method in the Helpers class that you want to operate on each instance of the tag searched for.</param>
        /// <returns></returns>
public static string stringTagIterator(string DataStr, string tag, string methodToRunOnTag)
        {
            if (DataStr.Length > 0)
            {
                StringBuilder newstr = new StringBuilder();
                int curPos = 0;
                int Loops = 0;
                do
                {
                    Loops++;
                    int tagLoc = DataStr.IndexOf("", tagLoc);
                    string tagstr = DataStr.Substring(tagLoc, (tagEndLoc + 1) - tagLoc);
                    newstr.Append(DataStr.Substring(curPos, tagLoc - curPos));
                    Type curclass = typeof(Helpers); //Helpers is the class this method is in
                    String tempstr = (String)curclass.InvokeMember(methodToRunOnTag, System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod, null, null, new Object[] { tagstr });
                    newstr.Append(tempstr);
                    curPos = tagEndLoc + 1;

                } while (Loops < 10000); //just a way to keep this loop from getting too carried away
                newstr.Append(DataStr.Substring(curPos));
                return newstr.ToString();
            }
            else
            {
                return "";
            }
        }
        public static string ensureAtagBlankTarget(string dataStr)
        {
            dataStr = dataStr.Replace("<A ","<a ");
            if (dataStr.IndexOf("target=\"_blank\"", StringComparison.InvariantCultureIgnoreCase).Equals(-1))
                dataStr = dataStr.Replace("<a ", "<a target=\"_blank\" ");
            return dataStr;
        }
}

The second method does the specific work on the tag data and then passes it back. The whole point of this though is that stringTagIterator can be called with a specific tag in mind and the name of a method that you would like to have operate on the tag found.

Follow

Get every new post delivered to your Inbox.