Thursday, May 19, 2011

Get bytes from Stream in c#

I know you may think what is the need of this post as this is very minor or simple to think and write. But, whenever I need to get bytes from a stream object, I always forgot it. This is simple but most of the times we used to Google. So, planned to write it to remember at least myself next time.
public byte[] GetBytesFromStream(Stream stream)
{
     byte[] buffer = new byte[16 * 1024];
     using (MemoryStream ms = new MemoryStream())
     {
        int read;
        while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
        {
           ms.Write(buffer, 0, read);
        }
        return ms.ToArray();
     } 
}
 

Check list exists in SharePoint site

This is very generic issue all SharePoint developers face at initial stages. As there is no default method available in SharePoint API to check whether if list exists in the SharePoint site, everyone write the below code:
SPList list = web.Lists["Task List"];
If(list != null)
{ 
    //Some code on list.
}
This is not correct to code like this. We all know generics and collections in c#. SPWeb.Lists is a collection and if you want to get one object from collection either we need to pass index or the key. If that didn’t find in the collection it gives us the exception. So, in our example if the Sharepoint site don’t have list named “Task List” then you will give run time exception in the line 1 itself. So, there is no point of checking whether list object is null. So, here is where many people stuck at. As Lists is plain collection object there is no other way of checking for the list exists in collection other than below.
private static bool ListExists(SPWeb web, string listName)
{
try
{
SPList list = web.Lists[listName];
}
catch
{
return false;
}
return true;
}
I know what you are thinking [Is this solution right?]. Yes, unfortunately there is no other way. So, we have to use this to check whether list exists in a SharePoint site.

Saturday, April 16, 2011

How to go to SharePoint Webpart Maintenance page for any page

This is one of the great tips we have in SharePoint. There are many scenarios why we need this. I had very tough time to migrate a SharePoint 2007 site to SharePoint 2010 site. What happened was,
  1. The other team deployed a custom web part 2 years ago.
  2. Used that web part on different pages in that site.
  3. They have taken the site template from the option "save site as template".
  4. After an year, they have removed  that web part from the site collection.
  5. But, with the same site template they have taken in the step #3, they created few sites in the same site collection after they removed the web part from environment.
  6. Remember, the site template still has the references to that custom web part. So, when I try to migrate it always fails..
Sometimes it is very difficult to find what is causing the problem. The sites created were not published sites. So, I cannot go to Edit Properties of the page and go to web part maintenance page from there. As the default.aspx page is directly in the root of the site/web I do not have any other choice to go to web part maintenance page. After a long research I found from Google that the querystring ?contents=1 will do job for me.

Resolution:
In SharePoint, for any web part ASPX page if you append the querystring ?contents=1 then it automatically redirects to the web part maintenance page.

Example: 
For the SharePoint site page
http://mossurl/default.aspx the web part maintenance page url is
http://mossurl/default.aspx?contents=1

Sunday, January 16, 2011

Clear and then disable controls in infopath

This is simple for reading, but difficult to implement in infopath forms. To disable controls we have to use “Conditional Formatting” option of a control. To clear content of a control then we have to use “Rules” option of a control. But, the sequence of execution of these two causes some problems. Take below scenario.
I have a table and each row the first column contains a checkbox and all other 4 columns are having date field, textbox, drop down and date field respectively. Now, the logic should be this.
  1. The default state of checkbox is selected.
  2. When user enter some data in all other 4 fields and now he thought the row should not allowed to enter data then he deselect the checkbox. When user deselects then the first thing should happen is clear the content in all the 4 controls and then all controls should be disabled.
  3. When again user select the checkbox then the controls should be enabled.
This is what to be happen and the first trail when I tried to implement I did below things.
  1. On all other 4 controls I added a rule that when checkbox selected state is false then set the current field to empty.
  2. And then I added a conditional formatting on them to disable when the checkbox state is unchecked.
I did deploy them to SharePoint and when I tested, surprisingly they are not working as expected. The controls are going to disable state but not clearing content in them when I deselect the checkbox. And researched and found that the Rules are not executing. [Didn’t find the reason yet.] And then thought about for alternatives and came up with reverse way. That is, applying rule on the checkbox instead of other controls.
Earlier, I have applied rules on the each and every individual control which needs to be cleared based on checkbox state – Which doesn’t work. Now, I have applied the same logic but applied rule on the checkbox [As there are 4 controls, 4 times I have added set field to empty] and which is working like charm.
So the conclusion I want to tell to you is, when I apply conditional formatting and then rules something is causing problems in the sequence of execution. So, depends on what your control, rules needs to be executed apply the rules on that control only. That should work perfect.

Date validation in Infopath forms

In SharePoint infopath forms I need to implement one thing which was a bit tricky as it is not the default supported by infopath forms. The requirement is like this: The date fields on form should not allow date plus/minus 5 years from current server date. For this, so many people recommended to implement validation events in c#. But, my form contains 40+ date fields. That is not possible to implement events for each control. But, when I looked into all option there is an option called “Data Validation”. But, there is no direct option available to implement this requirement.
After thought about sometime got wonderful ideas. Below is the implementation finally came up with.
  1. Select the date control and right click.
  2. Select the option “data validation”.
  3. Click on Add to add a new validation.
  4. From the window, the first thing we have to check is “Whether the field is blank or not.” Because once it is not blank then only we go further.
  5. And next thing is, validate the expression. User entered date is plus/minus 5 years from current date.
image
If you observe the first condition I have used is an expression as there is no direct way to validate the date according to my requirement.
Expression we have to use: msxsl:string-compare(., xdDate:AddDays(xdDate:Today(), 1825)) > 0 or msxsl:string-compare(., xdDate:AddDays(xdDate:Today(), -1825)) < 0
And second condition is just the field is not blank then only display “Invalid date” error on screen.
Note: Remember, the expression is very simple that adding/subtracting the 1825 days [5 years] to current date. Depends on your requirement please change the value accordingly.
The last reason why I have used the expression instead of the simple statements is the logical operators. The condition should be validated for this requirement is “((selected date > today + 5 years OR selected date < today – 5years) AND field cannot be blank)”. The brackets are very important, the sequence of executing conditions and logical operators are important. So, to achieve this in infopath forms the only way is implementing expressions. Then only it treats it as the way we want. Enjoy the complex and nice series of posts on infopath and sharepoint coding.

Delete event receiver from a SharePoint list

In my previous post, we saw how we added an event receiver to a list. Now, we will see how to delete the existing event receiver on a list.
private void DeleteEventReceiverFromAList(string siteUrl)
    {
        using (SPSite site = new SPSite(siteUrl))
        {
            using(SPWeb web = site.OpenWeb())
            {
                try
                {
                    SPList list = web.Lists["myList"];
                    if (list != null)
                    {
                        string className = "EventReceiverClass";
                        string asmName = "EventReceiverAssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a865f0ecc234ea51";
                        web.AllowUnsafeUpdates = true;

                        int receivers = list.EventReceivers.Count;
                        bool isAddedReceiverExist = false;
                        bool isUpdatedReceiverExist = false;
                        for (int i = 0; i < receivers; i++)
                        {
                            SPEventReceiverDefinition eventReceiver = list.EventReceivers[i];
                            if (eventReceiver.Class == className && eventReceiver.Type == SPEventReceiverType.ItemAdded)
                            {
                                eventReceiver.Delete();
                                break;
                            }
                        }
                    }
                }
                catch { }
                finally
                {
                    web.AllowUnsafeUpdates = false;
                }
            }
        }
    }
In this code also, there is nothing to explain very detail. Please let me know if you have any questions.

Add event receiver to a SharePoint list

This is very generic and everyone knows how to add an event receiver. But, usually we attach the event receiver on a list template, site etc. This post deals with adding event receiver to a specific list.
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;
}
}
}
}
This is very straight forward code and hope you got it.

Hide content types from a SharePoint library through coding

Please read the post here.

Change content type order in NEW button of a SharePoint library

This is continuation of my previous post. After you read that post you get clear understanding of how we added the content types to a library through coding. But, what if there is a requirement we need this content type order to be shown when I select the NEW button from the list tool bar or hide some content types? Then again we need some sort of code which does that for all existing lists as we cannot change manually if there are plenty of webs in a site.
private void ChangeOrHideContentTypesInALibrary(SPList list)
{
list.ContentTypesEnabled = true;

SPFolder folder = list.RootFolder;

List<SPContentType> orderedContentTypes = new List<SPContentType>();
foreach (SPContentType ct in folder.ContentTypeOrder)
{
if (ct.Name.Contains("ContentType1") || ct.Name.Contains("ContentType2"))
orderedContentTypes.Add(ct);
}

folder.UniqueContentTypeOrder = orderedContentTypes;
folder.Update();
}

If you observe the above code, then the variable orderedContentTypes is what having the content types of which we need to show in the NEW button of the list toolbar. In which order we add the content types to this variable, that order they will be added to the list and shown on the toolbar. And second thing is out of 3 content types available in the above logic we have added only two to the variable. So the third content type will be hidden from the toolbar. And the last two lines in the above function are to update the list with the latest content types order.

Hope this gives you clear idea on how to order and hide content types on a list/library.