Wednesday, March 16, 2011

Editable Dropdown list with IE6 issue resolved

I came across the situation when I wanted to give the user the option of either creating a new entry or selecting from an existing one. 



Solution is here...
The textbox is placed on top of the dropdown with enough room on the right to still display the down arrow of the dropdown. You can see that the user is either able to enter new text into the textbox or select an option from the dropdown.
To display the box properly I use HTML and CSS. When the user selects an option from the dropdown I use Javascript to load the value into the textbox. When the form is submitted ignore the dropdown and just pull the value from the textbox.

<script language="javascript" type="text/javascript">
function DropDownTextToBox(objDropdown, strTextboxId)
{
    document.getElementById(strTextboxId).value = objDropdown.options[objDropdown.selectedIndex].value;
    DropDownIndexClear(objDropdown.id);
    document.getElementById(strTextboxId).focus();
}
</script>

This is the HTML that includes the textbox, dropdown and the div that goes around it. You’ll notice IE conditional statements in commented area for IE6 issue.
<div style="position: relative;">
    <!--[if lte IE 6.5]><div class="select-free" id="dd3"><div class="bd" ><![endif]-->
    <input name="TextboxExample" type="text" maxlength="50" id="TextboxExample" tabindex="2"
        onchange="DropDownIndexClear('DropDownExTextboxExample');" style="width: 242px;
        position: absolute; top: 0px; left: 0px; z-index: 2;" />
    <!--[if lte IE 6.5]><iframe></iframe></div></div><![endif]-->
    <select name="DropDownExTextboxExample" id="DropDownExTextboxExample" tabindex="1000"
        onchange="DropDownTextToBox(this,'TextboxExample');" style="position: absolute;
        top: 0px; left: 0px; z-index: 1; width: 265px;">
        <option value="Value for Item 1" title="Title for Item 1">Item 1</option>
        <option value="Value for Item 2" title="Title for Item 2">Item 2</option>
        <option value="Value for Item 3" title="Title for Item 3">Item 3</option>
    </select>
</div>

IE6 Problem:
The above implementation wont work in IE 6. It wasn’t able to display the textbox over the dropdown properly.
The following style code is used to overcome the issues with IE6.

<style type="text/css">
    .select-free
    {
        position: absolute;
        z-index: 10; /*any value*/
        overflow: hidden; /*must have*/
        width: 247px; /*must have for any value*/ /*width of area +5*/
    }
    .select-free iframe
    {
        display: none; /*sorry for IE5*/
        display: block; /*sorry for IE5*/
        position: absolute; /*must have*/
        top: 0px; /*must have*/
        left: 0px; /*must have*/
        z-index: -1; /*must have*/
        filter: mask(); /*must have*/
        width: 3000px; /*must have for any big value*/
        height: 3000px /*must have for any big value*/;
    }
    .select-free .bd
    {
        padding: 11px;
    }
</style>

Friday, March 11, 2011

The Web application at ... could not be found. Verify that you have typed the URL correctly.

Yesterday my colleague showed me this error. He was trying to open a SPSite object using a URL and hitting the following error: 

The Web application at ... could not be found. Verify that you have typed the URL correctly. If the URL should be serving existing content, the system administrator may need to add a new request URL mapping to the intended application.

This is common, and can have several causes.

1. The obvious: The URL does not exist on the farm.  

Solution: Change the URL you are loading to the correct one.  

2. The not so obvious: the code is in a console or windows application which you are now running with an account that does not have permissions to connect to the SQL server. 

Solution: either run the application as a different user or grant the user permissions on the SQL database.

3. The last but most important: the code is in a console or windows application that is compiled with platform target x86, while your SharePoint server is x64. 

Solution: set the platform target to "Any CPU".

Friday, March 4, 2011

Add event receiver to a SharePoint list

Recently I have created a generic function to add event receiver to specific SharePoint list.
Explaination is not need as code is very simple to understand.

private void AddEventReceiverToAList(string siteUrl)
{
    using (SPSite site = new SPSite(siteUrl))
    {
        using (SPWeb web = site.OpenWeb())
        {
            try
            {
                SPList list = web.Lists["myList"];
                if (list != null)
                {
                    int receivers = list.EventReceivers.Count;
                    string className = "EventReceiverClass";
                    string asmName = "EventReceiverAssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a865f0ecc234ea51";
                    web.AllowUnsafeUpdates = true;
                    bool isAddedReceiverExist = false;
                    for (int i = 0; i < receivers; i++)
                    {
                        SPEventReceiverDefinition eventReceiver = list.EventReceivers[i];
                        if (eventReceiver.Class == className && eventReceiver.Type == SPEventReceiverType.ItemAdded)
                        {
                            isAddedReceiverExist = true;
                            break;
                        }
                    }
                    if (!isAddedReceiverExist)
                        list.EventReceivers.Add(SPEventReceiverType.ItemAdded, asmName, className);
                }
            }
            catch { }
            finally
            {
                web.AllowUnsafeUpdates = false;
            }
        }
    }

Wednesday, March 2, 2011

The service 'System.Workflow.ComponentModel.Compiler.ITypeProvider' must be installed for this operation to succeed. Please ensure that this service is available.

Yesterday I was creating a Visual studio workflow, so I have created a WSPBuilder Project and added ‘State Machine Workflow feature’ template. When I tried to open the workflow it gave me following error:

The service 'System.Workflow.ComponentModel.Compiler.ITypeProvider' must be installed for this operation to succeed.  Please ensure that this service is available.

To fix this issue you have to edit your project file:

<Project>
<PropertyGroup>
            <ProjectTypeGuids> {14822709-B5A1-4724-98CA-57A101D1B079};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}ProjectTypeGuids>

Note: You will not encounter above error in ‘WSPBuider Project with Workflow' template.

Reference link: 

Tuesday, March 1, 2011

Update SharePoint default application pages (AccessDenied.aspx, SignOut.aspx) with your own custom pages

I came across the situation where I need to replace the default SignOut.aspx page with custom page.
The following feature receiver replaces the default SignOut page with a custom one on activation and resets the SignOut page to the default one on deactivation.

[Guid("d8ed5819-b368-493f-a59c-1167c2a63799")]
public class UpdateDefaultPageEventReceiver : SPFeatureReceiver
{
    const string customPage = "_layouts/MyPage/CustomSignOut.aspx";
    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
        if (null != webApp)
        {
            if (!webApp.UpdateMappedPage(SPWebApplication.SPCustomPage.Signout, customPage))
            {
                //Unable to replace the SignOut page
            }
        }
    }

    public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
    {
        SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
        if (null != webApp)
        {
            if (!webApp.UpdateMappedPage(SPWebApplication.SPCustomPage.Signout, null))
            {
                //Unable to reset the SignOut page
            }
        }
    }
}

You can also replace other pages which are member of SPWebApplication.SPCustomPage enum. (e.g. AccessDenied.aspx, Confirmation.aspx, Error.aspx, Login.aspx, ReqAcc.aspx, SignOut.aspx etc.)