Archive for August, 2009

08/28/09
Fahad Zia
tags:  

Find total number of Web Parts in a Web Part Zone


I was using feature to insert web parts in particular zones when activated which worked fine except it wouldnt check if there is a webpart already in a web part zone and my requirement was not to insert web parts in zones where there is already one. So to do this I used the following code which did not work:

try
{
   SPFile file = web.GetFile(web.Url + @"/Pages/" + strPage);
   file.CheckOut();
   SPLimitedWebPartManager wpMgr = file.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared); 	

   foreach (WebPart wp in wpMgr.WebParts)
   {
      //wp.Zone is always null
   }
}

For some reason wp.Zone was always null! and I couldnt use wp.Zone.WebParts.Count to find out the number of web parts in the zone. The property I could use was wp.ZoneID which was a string. Here is the code that worked for me:

ArrayList arrlstExistingWPs = new ArrayList();
Dictionary<string, int> dictZoneWPs = new Dictionary<string, int>();
for (int i = 0; i < wpMgr.WebParts.Count; i++)
{
    WebPart wp = wpMgr.WebParts[i] as WebPart;
    if (wp != null)
    {
        arrlstExistingWPs.Add(wp.Title);
        if (!dictZoneWPs.ContainsKey(wp.ZoneID))
        {
            dictZoneWPs.Add(wp.ZoneID, 0);
        }
        dictZoneWPs[wp.ZoneID] += 1;
    }
}

and then i can use it using some checks:

strWPTitle="WebPart1";
strZone = "TopLeftZone";
if (!arrlstExistingWPs.Contains(strWPTitle) && 
     !dictZoneWPs.ContainsKey(strZone))
{
  //insert webpart
}

Fahad Zia

Delete all Web Parts on a SharePoint publishing page


In one of the sharepoint features I developed, I had to delete all webparts on default.aspx page when the feature is activated so I started out by using this code:

SPLimitedWebPartManager wpMgr = file.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
for (int i =0; i< wpMgr.WebParts.Count; i++)
{
    wpMgr.DeleteWebPart(wpMgr.WebParts[i]);
}

this strangely DOES NOT work. It will not delete all webparts on the pages. What works is if you loop through in reverse order like this:

SPLimitedWebPartManager wpMgr = file.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
for (int i = wpMgr.WebParts.Count; i >0 ; i--)
{
    wpMgr.DeleteWebPart(wpMgr.WebParts[i-1]);
}

If anyone knows why reverse loop works please let me know.


Fahad Zia
tags:  

Get all emails from the permitted groups/users of the list


Here’s how you can get the list of all users that have permissions on the list.

private List<string> GetEmailsFromRoleAssignment(Guid guidList, string strWebURL)
{    
    List<string> lstUserEmails = new List<string>();

    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        try
        {
            using (SPSite site = new SPSite(SPContext.Current.Site.ID))
            {
                using (SPWeb web = site.OpenWeb(strWebURL))
                {
                    SPList list = web.Lists[guidList];

                    SPRoleAssignmentCollection oRoleAssignments = list.RoleAssignments;
                    foreach (SPRoleAssignment oRoleAssignment in oRoleAssignments)
                    {
                        SPPrincipal oPrincipal = oRoleAssignment.Member;
                        try
                        {
                            // Retrieve users having explicit permissions on the list
                            SPUser oRoleUser = (SPUser)oPrincipal;
                            if (!string.IsNullOrEmpty(oRoleUser.Email) && !lstUserEmails.Contains(oRoleUser.Email))
                            {
                                lstUserEmails.Add(oRoleUser.Email);
                            }
                        }
                        catch (Exception ex)
                        {
                            string msg = ex.Message;
                        }
                        try
                        {
                            // Retrieve user groups having permissions on the list
                            SPGroup oRoleGroup = (SPGroup)oPrincipal;

                            if (oRoleGroup.Users.Count > 0)
                            {
                                string strGroupName = oRoleGroup.Name;
                                // code to retrieve Users inside this User-Group
                                foreach (SPUser user in oRoleGroup.Users)
                                {
                                    if (!string.IsNullOrEmpty(user.Email) && !lstUserEmails.Contains(user.Email))
                                    {
                                        lstUserEmails.Add(user.Email);
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            string msg = ex.Message;
                        }
                    }
                }

            }
        }
        catch (Exception ex)
        {

        }
        
    });

    return lstUserEmails;   
}

Reference(s):

08/11/09
Fahad Zia
tags:  

InfoPath: The form has been closed


I tried to add this workflow which had this association form but I would get this message and the form would not load : “The form has been closed”. Looking in the logs I saw this error: “InfoPathLocalizedException, Exception Message: The specified form cannot be found”. Looking online for the solution I saw various posts talking about checking form URN, location etc which I already made sure. One of the posts pointed to Central Admin->Application Management->Manage Form Templates where I should be able to see all the installed InfoPath form templates. What I noticed is my form name was “association.xsn” and there was already another InfoPath form called “association.xsn” that was already deployed by me few weeks ago. I did not know that i had to make my form name unique otherwise the new form is not installed. To verify this I tried uploading the new “association.xsn” from the central admin and after cliking Verify I saw this warning:
ip1

So you know what I would do next right ;), I renamed my form to “mywfname_association.xsn” , verified and saw no warning. I redeployed my solution with this new form and everything went fine and I could see the new association form in my workflow.


Fahad Zia

SharePoint Snippets


Probably documented hundred times else where but I will post it anyway. To make your life easy when developing SharePoint solutions add these .snippet files by pressing Ctrl + K + B in VS and browse to:

C:\Program Files\Microsoft Visual Studio 8\Xml\1033\Snippets\SharePoint Server Workflow

Now when you right click on Code View and choose Insert Snippet you will see snippets menu as in the screenshot below:

snippet1

08/07/09
Fahad Zia
tags:  

Export to Excel Web Part


I recently came across an issue while exporting list that had Custom Field Types columns that wouldnt show up when exported to Excel 2003 although it worked fine in Excel 2007. To make it work in Excel 2003 i developed a webpart that would take list name and view name and export the data in xls format which can both be viewed in Excel 2007 and Excel 2003.

The code is pretty straightforward in btn_Click event except if you dont have btn.OnClientClick = “_spFormOnSubmitCalled = false;_spSuppressFormOnSubmitWrapper=true;”; , the list can be exported only once after which the UI becomes unresponsive, this is due to secuirty in SharePoint handled by javascript properties _spFormOnSubmitCalled and _spSuppressFormOnSubmitWrapper. Here is the code that worked for me:

protected override void CreateChildControls()
{
    base.CreateChildControls();

    if (string.IsNullOrEmpty(strListName) || string.IsNullOrEmpty(strViewName))
    {
        return;
    }

    SPWeb web = SPControl.GetContextWeb(HttpContext.Current);

    Button btn = new Button();
    btn.Text = strButtonTitle;
    btn.Click += new EventHandler(btn_Click);
    //without the following onclientclick the page controls become unresponsive after the first export
    btn.OnClientClick = "_spFormOnSubmitCalled = false;_spSuppressFormOnSubmitWrapper=true;";
    btn.Attributes.Add("style", "margin: 5px");
    this.Controls.Add(btn);

    lblErr.ForeColor = Color.Red;
    lblErr.Font.Size = FontUnit.Point(8);
    lblErr.Font.Bold = true;
    lblErr.Visible = false;
    this.Controls.Add(lblErr);
}




void btn_Click(object sender, EventArgs e)
{
    //query list from current web
    //SPWeb web = SPControl.GetContextWeb(HttpContext.Current);
    SPWeb web = SPContext.Current.Site.OpenWeb(SPContext.Current.Web.ServerRelativeUrl); 
    SPQuery query = new SPQuery();
    query.Query = "<Where><Neq><FieldRef Name='Title'/><Value Type='Text'>$</Value></Neq></Where>";
  
    DataTable dt = null;
    try
    {
        SPList list = web.Lists[strListName];
        SPView view = list.Views[strViewName];
        query.ViewFields = view.ViewFields.SchemaXml;

        SPListItemCollection items = list.GetItems(query);
        dt = items.GetDataTable();

        this.Page.Response.Clear();
        this.Page.Response.AddHeader("content-disposition", "attachment;filename=report.xls");
        this.Page.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        this.Page.Response.ContentType = "application/vnd.ms-excel";
        Page.Response.BufferOutput = true;
        this.Page.Response.Buffer = true;
        EnableViewState = false;
        this.Page.Response.Charset = "";

        StringWriter strW = new StringWriter();
        HtmlTextWriter htmlw = new HtmlTextWriter(strW);
        htmlw.RenderBeginTag(HtmlTextWriterTag.Table);

        //make header row
        DataTable dtClone = dt.Clone();     //clone doesnt copy data but structure
        htmlw.RenderBeginTag("tr");
        foreach (DataColumn column in dt.Columns)
        {
            htmlw.RenderBeginTag("td"); // Add a cell
            htmlw.RenderBeginTag("b");
            htmlw.Write(column.ColumnName);
            htmlw.RenderEndTag();
            htmlw.RenderEndTag();
        }
        htmlw.RenderEndTag();

        //export datatable
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            DataRow row = dt.Rows[i];
            htmlw.RenderBeginTag("tr"); //Add a row
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                DataColumn column = dt.Columns[j];
                htmlw.RenderBeginTag("td"); // Add a cell
                htmlw.Write(row[column].ToString());
                htmlw.RenderEndTag();
            }

            htmlw.RenderEndTag();
        }
        htmlw.RenderEndTag();

        this.Page.Response.Write(strW.ToString());
        Page.Response.Flush();
        Page.Response.End();

    }
    catch (Exception ex)
    {
        lblErr.Visible = true;
        lblErr.Text = "* " + ex.Message;
    }

}

Here are the link(s) i found useful:


Fahad Zia
tags:  

PeopleEditor/PeoplePicker control as Web Part property


Sooner or later in your SharePoint development you will come across this requirement where you have to use PeopleEditor control and manipulate it in your web part code. You cannot use PeopleEditor as custom property of your web part as you would use string, int. There may be other ways to include it but in this post I will show how I used ToolPart to include it as an editable property of my web part.

Here is the web part code:

public class DiscussionBoardArchiveWebPart : Microsoft.SharePoint.WebPartPages.WebPart
{
    private string _strListName;

    [Personalizable(PersonalizationScope.Shared)]
    [WebBrowsable(true)]
    [SPWebCategoryName("List")]
    [WebDisplayName("Name")]
    public string strListName
    {
     get { return _strListName; }
     set { _strListName = value; }
    }
    private string _From;
    public string From
    {
        get
        {
            return _From;
        }
        set
        {
            _From = value;
        }
    }   

    public DiscussionBoardArchiveWebPart()
    { }

    protected override void CreateChildControls()
    {
       

    }
   
    public override ToolPart[] GetToolParts()
    {
        ToolPart[] toolparts = new ToolPart[3];

        WebPartToolPart wptp = new WebPartToolPart();
        CustomPropertyToolPart customtp = new CustomPropertyToolPart();
        PeopleEditorToolPart ppltp = new PeopleEditorToolPart("From");

        toolparts[0] = ppltp;
        toolparts[1] = wptp;
        toolparts[2] = customtp;

        return toolparts;
    }


}

Code of interest is overriding the GetToolParts() function. WebPartToolPart is the default edit UI you see when you modify a web part. CustomPropertyToolPart is the UI you see when modify web part to edit custom properties , in this example to edit _strListName property. And finally the custom toolpart we have to show the PeopleEditor control. Note that the order in which you add these to the ToolPart[] array is how it will appear in the interface, so in this example PeopleEditorToolPart shows on top as can be seen in the screenshot below:
db1

Now the PeopleEditorToolPart class code:

    class PeopleEditorToolPart : ToolPart
    {
        PeopleEditor pe = null;
        private void PeopleEditorToolPart_Init(object sender, EventArgs e)
        {
            
            pe = new PeopleEditor();
            pe.ID = "PeopleEditorWebPart";
            pe.AllowEmpty = false;
            pe.ValidatorEnabled = true;
            pe.MultiSelect = true;
            pe.SelectionSet = PeopleEditor.AccountType.User.ToString();

            //show accounts already saved
            SyncChanges();
        }

        public PeopleEditorToolPart(string strTitle)
        {
            this.Title = strTitle;
            this.Init += new EventHandler(PeopleEditorToolPart_Init);
        }

        public override void ApplyChanges()
        {
            DiscussionBoardArchiveWebPart parentWP = (DiscussionBoardArchiveWebPart)this.ParentToolPane.SelectedWebPart;            
            parentWP.To = pe.CommaSeparatedAccounts;
        }

        public override void SyncChanges()
        {
            EnsureChildControls();
            DiscussionBoardArchiveWebPart parentWP = (DiscussionBoardArchiveWebPart)this.ParentToolPane.SelectedWebPart;
            pe.CommaSeparatedAccounts = parentWP.To;
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            Controls.Add(pe);
        }
  }

After this you can manipulate the PeopleEditor accounts in any way you want. Here is how you will save them to an array say for example in CreateChildControls()

string[] strAccounts = _From.Split(',');

Reference(s):


Fahad Zia
tags:   ,

Using jCrop for cropping document library images


In one of recent projects I had to provide the ability of cropping images for document library images. I googled to see what my options were and when I saw jCrop demo I thought it would be a good solution for the requirement. So next thing I did was look for jCrop and ASP.NET samples and here are the two most helpful ones i came across:

1. Upload and Crop Images with jQuery, JCrop and ASP.NET
2. ASP.NET Web Crop Image Control

OK, so now all i have to is create an application page and custom action that will link the image to this page.

Here is how the completed solution looks like: (Please note that you have to include jCrop and jQuery .css and .js files in your page for this to function, my solution assumes that you have them included in your page either using Content Editor Web Part or Master Page)
jcrop1
jcrop2
jcrop3
Image after cropping
Here is the code for my application page:

public class ImageCrop : LayoutsPageBase
{
    private const string WIDTH = "450";
    private const string HEIGHT = "200";
    protected Image imgJCrop;
    protected Button btnCropImage;
    protected Button btnCropImageTop;
    string strImageURL;
    protected Label lblErr;
    protected TextBox txtW;
    protected TextBox txtH;
    protected Button btnApplyDimensions;

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        this.EnsureChildControls();

        //load jCrop script
        ClientScriptManager sm = Page.ClientScript;
        sm.RegisterHiddenField("jCropX", "0");
        sm.RegisterHiddenField("jCropY", "0");
        sm.RegisterHiddenField("jCropW", WIDTH);
        sm.RegisterHiddenField("jCropH", HEIGHT);

        string strScript = string.Format("<script type='text/javascript'>" +
                                        "var globalX=0;" +
                                        "var globalY=0;" +
                                        "jQuery(document).ready(function() {{" +
                                        "var jcropAPI = $.Jcrop('#{0}',{{onChange: storeCoords}});" +
                                        "jcropAPI.setSelect([0,0,{1},{2}]);" +

                                            "jQuery('#{11}').click(function(e) {{" +
                                            "jcropAPI.setSelect([globalX,globalY,jQuery('#{9}').val(),jQuery('#{10}').val()]); }});" +

                                        "}});" +

                                        "function nothing(e) {{" +
                                        "e.stopPropagation(); e.preventDefault(); return false;" +
                                        "}};" +

                                        "function storeCoords(c) {{" +
                                        "jQuery('#{3}').val(c.x); " +
                                        "jQuery('#{4}').val(c.y);" +
                                        "jQuery('#{5}').val(c.w);" +
                                        "jQuery('#{6}').val(c.h);" +
                                        "jQuery('#{7}').val(c.w);" +
                                        "jQuery('#{8}').val(c.h);" +
            //"globalX = c.x;" + 
            //"globalY=c.y;" + 
                                        "}};" +
                                        "</script>",
                                        imgJCrop.ClientID,
                                        WIDTH,
                                        HEIGHT,
                                        "jCropX",
                                        "jCropY",
                                        "jCropW",
                                        "jCropH",
                                        txtW.ClientID,
                                        txtH.ClientID,
                                        txtW.ClientID,
                                        txtH.ClientID,
                                        btnApplyDimensions.ClientID);
        this.RegisterStartupScript("jCropJS", strScript);

        //diable server side on button click
        btnApplyDimensions.OnClientClick = "return false;";

        //load image
        //SPSite sitecoll = this.Site;
        if (Request.QueryString["ItemUrl"] != null)
        {
            if (this.Web.ServerRelativeUrl != "/")
                {
                    strImageURL = this.Web.Url.TrimEnd('/') + Request.QueryString["ItemUrl"].ToString().Replace(this.Web.ServerRelativeUrl, "");
                }
                else
                {
                    strImageURL = this.Web.Url.TrimEnd('/') + Request.QueryString["ItemUrl"].ToString();
                }
                
                imgJCrop.ImageUrl = strImageURL;
        }

    }


    protected void btnCropImage_Click(object sender, EventArgs e)
    {
        int x = Convert.ToInt32(Page.Request["jCropX"]);
        int y = Convert.ToInt32(Page.Request["jCropY"]);
        int w = Convert.ToInt32(Page.Request["jCropW"]);
        int h = Convert.ToInt32(Page.Request["jCropH"]);

        string strListID = Request.QueryString["ListId"];
        //string strWebURL = Request.QueryString["SiteUrl"];
        string strItemID = Request.QueryString["ItemId"];

        lblErr.Style.Add(HtmlTextWriterStyle.Color, "Red");
        lblErr.Style.Add(HtmlTextWriterStyle.FontSize, "11px");
        lblErr.Style.Add(HtmlTextWriterStyle.FontWeight, "bold");
        lblErr.Visible = true;

        SPSecurity.RunWithElevatedPrivileges(delegate()
        {
            try
            {
                using (SPSite site = new SPSite(this.Site.Url))
                {
                    using (SPWeb web = site.OpenWeb(this.Web.ServerRelativeUrl))
                    {

                        try
                        {
                            web.AllowUnsafeUpdates = true;

                            SPList list = web.Lists[new Guid(strListID)];
                            SPListItem item = list.Items.GetItemById(Convert.ToInt32(strItemID));
                            SPFile file = item.File;

                            if (list.WorkflowAssociations.Count > 0)
                            {
                                //dont crop as it can effect workflow
                                lblErr.Text = "The document library this image belongs to has workflow enabled. Please disable workflows on this document library to enable cropping";

                                btnCropImage.Enabled = false;
                                btnCropImageTop.Enabled = false;
                                return;
                            }
                            else
                            {
                                lblErr.Visible = false;
                            }

                            if (file.CheckOutStatus != SPFile.SPCheckOutStatus.None)
                            {
                                file.CheckIn("");
                            }

                            file.CheckOut();

                            //use WebRequest to create stream to the document library file
                            WebRequest reqImg = WebRequest.Create(strImageURL);
                            reqImg.UseDefaultCredentials = true;
                            WebResponse imgResponse = reqImg.GetResponse();
                            StreamReader reader = new StreamReader(imgResponse.GetResponseStream());

                            using (System.Drawing.Image imgOriginal = System.Drawing.Image.FromStream(reader.BaseStream, true))
                            {
                                using (System.Drawing.Image imgCropped = new System.Drawing.Bitmap(w, h))
                                {
                                    using (System.Drawing.Graphics graphic = System.Drawing.Graphics.FromImage(imgCropped))
                                    {
                                        graphic.SmoothingMode = SmoothingMode.AntiAlias;
                                        graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
                                        graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;

                                        System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, w, h);
                                        graphic.DrawImage(imgOriginal, rect, x, y, w, h, System.Drawing.GraphicsUnit.Pixel);

                                        MemoryStream mstream = new MemoryStream();
                                        imgCropped.Save(mstream, imgOriginal.RawFormat);

                                        MemoryStream msNew = null;
                                        using (msNew = new MemoryStream(mstream.GetBuffer(), 0, mstream.GetBuffer().Length))
                                        {
                                            msNew.Write(mstream.GetBuffer(), 0, mstream.GetBuffer().Length);
                                            list.RootFolder.Files.Add(file.Name, msNew.ToArray(), true);
                                            file.Item.SystemUpdate(false);
                                            file.CheckIn("");
                                        }
                                    }
                                }
                            }

                            web.AllowUnsafeUpdates = false;
                        }
                        catch (Exception ex)
                        {
                            lblErr.Visible = true;
                            lblErr.Text = ex.Message;
                            if (web.AllowUnsafeUpdates != false)
                            {
                                web.AllowUnsafeUpdates = false;
                            }
                        }

                    }
                }
            }
            catch (Exception ex)
            {
                lblErr.Visible = true;
                lblErr.Text = ex.Message;
            }

        });
    }

}

I will not go in the details of the code as they are better explained on the offical jCrop plugin page but here is the brief description; basically javascript function assigns the jCrop plugin to the image tag by this line: var jcropAPI = $.Jcrop(‘#{0}’,{{onChange: storeCoords}}); The x, y, width and height is saved in hidden fields by storeCoords javascript function when the user changes the dimensions of the box in the image and then these hidden fields are read by .NET code on postback to crop the image. The btnApplyDimensions button is what you see as “Apply” button in the image which lets the user type in the exact dimensions he wants to crop the image to.
Finally, to display custom action here is the elements.xml that shows the custom action for GIF, JPG and PNG files

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Title="Crop Image" 
    ImageUrl="/_layouts/images/icon_crop.png"
    Location="EditControlBlock"
    RegistrationType="FileType"
    RegistrationId="jpg">
    <UrlAction Url="javascript:window.location= '{SiteUrl}/_layouts/imagecrop.aspx?ItemUrl={ItemUrl}&amp;ItemId={ItemId}&amp;ListId={ListId}&amp;Source=' + window.location"/>
  </CustomAction>
  <CustomAction Title="Crop Image"
    ImageUrl="/_layouts/images/icon_crop.png"
    Location="EditControlBlock"
    RegistrationType="FileType"
    RegistrationId="gif">
    <UrlAction Url="javascript:window.location= '{SiteUrl}/_layouts/imagecrop.aspx?ItemUrl={ItemUrl}&amp;ItemId={ItemId}&amp;ListId={ListId}&amp;Source=' + window.location"/>
  </CustomAction>
  <CustomAction Title="Crop Image"
    ImageUrl="/_layouts/images/icon_crop.png"
    Location="EditControlBlock"
    RegistrationType="FileType"
    RegistrationId="png">
    <UrlAction Url="javascript:window.location= '{SiteUrl}/_layouts/imagecrop.aspx?ItemUrl={ItemUrl}&amp;ItemId={ItemId}&amp;ListId={ListId}&amp;Source=' + window.location"/>
  </CustomAction>
</Elements>

Fahad Zia
tags:  

Set top navigation bar headings programmatically


SPNavigationNode doesnt support headings, you can use SPNavigationSiteMapNode to create them. Example:

SPNavigationNodeCollection topNavigationBar = webRoot.Navigation.TopNavigationBar;
SPNavigationNode wgNode = SPNavigationSiteMapNode.CreateSPNavigationNode("Toolbox", "", Microsoft.SharePoint.Publishing.NodeTypes.Heading, topNavigationBar);
SPNavigationNode intranetNode = new SPNavigationNode("Intranet", "http://www.xxxmycompanyxxx.net",true);
wgNode.Children.AddAsFirst(intranetNode);
SPNavigationNode internetNode = new SPNavigationNode("Internet", "http://www.xxxxmycompanyxxxx.com",true);
wgNode.Children.Add(internetNode,intranetNode);

this will create Toolbox heading with Internet and Intranet as submenus.

Reference(s):


Fahad Zia
tags:  

Overwrite files using SharePoint Feature


SharePoint features doesnt let you overwrite files in the content database programmatically. You have to use feature activation events to do it using object model. The property that comes close is “IgnoreIfAlreadyExists” but it doesnt replace files, it can alert if a filename already exists in content database. Sometimes its necessary that your feature has to overwrite files on SharePoint filesystem and not just content database. This post will demonstrate 2 ways of what has worked for me:

1. Overwrite files in content database.

Lets say I have developed a custom master page that is used by the site collection and has been provisioned as part of my feature. Now there are some changes that need to be done on this masterpage and needs to be reprovisioned to this site. Here is my how my feature.xml looks like(I am only showing the Properties tag), in this example I am replacing two files company_site.master and homepage_layout_v2.aspx in the site collection Master Page Gallery:

<Properties>
    <Property Key="overwritemasterpagefile1" Value="company_site.master"/>
    <Property Key="overwritemasterpagefile2" Value="homepage_layout_v2.aspx"/>     
</Properties>

Note: these two files are copied to the features directory in MasterPages folder using solution so they can be accessed from feature events.
and here is how the files are replaced on feature activation:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    SPSite site = properties.Feature.Parent as SPSite;
    UpdateMasterpageGallery(properties, site.RootWeb);
}

private static void UpdateMasterpageGallery(SPFeatureReceiverProperties properties, SPWeb web)
{
    ArrayList arrlstMasterpageFilesToOverwrite = new ArrayList();
    foreach (SPFeatureProperty p in properties.Feature.Properties)
    {
        if (p.Name.StartsWith("overwritemasterpagefile"))
        {
            arrlstMasterpageFilesToOverwrite.Add(p.Value);
        }
    }            

    using (web)
    {
    for (int i = 0; i < arrlstMasterpageFilesToOverwrite.Count; i++)
    {
        //SPFile fileMasterpage = web.Lists["Master Page Gallery"].RootFolder.Files["woodgroup_site.master"];
        string strFileName = arrlstMasterpageFilesToOverwrite[i].ToString();
        string strFileNameWithoutExt = Path.GetFileNameWithoutExtension(strFileName);
        string strFileExt = Path.GetExtension(strFileName);

        SPFile fileMasterpage = web.GetFile("_catalogs/masterpage/" + strFileName);
        if (fileMasterpage != null)
        {
            if (fileMasterpage.CheckOutStatus != SPFile.SPCheckOutStatus.None)
            {
                fileMasterpage.CheckIn("checked in by feature");
            }
            fileMasterpage.CheckOut();

            //backup file will show up in Master Page/Page Layout dropdowns so either Hide them or dont make a backup
            //fileMasterpage.CopyTo(web.Url + "/_catalogs/masterpage/" + strFileNameWithoutExt + "_" + DateTime.Now.ToString("ddMMyyyyhhmmss") + strFileExt);

            string strPathNewMasterPage = properties.Definition.RootDirectory + "/MasterPages/" + strFileName;
            
            if (File.Exists(strPathNewMasterPage))
            {
                byte[] fcontents = File.ReadAllBytes(strPathNewMasterPage);
                web.Lists["Master Page Gallery"].RootFolder.Files.Add(strFileName, fcontents, true);

                fileMasterpage.Update();                            
                fileMasterpage.CheckIn("checked in by feature");
                fileMasterpage.Publish("sucessfully published by feature");
                fileMasterpage.Approve("approved by site feature");
            }
        }
        
    }
}          

2. Overwrite files in LAYOUTS directory of the 12 Hive

feature.xml looks like this:

<Properties>
 <!-- layouts files have path included so it can be copied to the right path, these path are relative to LAYOUTS directory -->   
  <Property Key="overwritelayoutfile1" Value="STYLES\theme.css" /> 
  <Property Key="overwritelayoutfile2" Value="jquery\thickbox.js" />
</Properties>

Note: these two files are copied to the features directory using solution so they can be accessed from feature events.

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    SPSite site = properties.Feature.Parent as SPSite;
    UpdateLayoutFiles(properties);
}

private void UpdateLayoutFiles(SPFeatureReceiverProperties properties)
{
    //layouts/styles/woodgroup
    //if layout files exist delete/backup and write the new file
    ArrayList arrlstLayoutFilesToOverwrite = new ArrayList();
    foreach (SPFeatureProperty p in properties.Feature.Properties)
    {
        if (p.Name.StartsWith("overwritelayoutfile"))
        {
            arrlstLayoutFilesToOverwrite.Add(p.Value);
        }
    }

    for (int i = 0; i < arrlstLayoutFilesToOverwrite.Count; i++)
    {
        //check if file exists in the path 
        //backup and write from the copy in the feature directory

        //NOTE: filename has relative path to LAYOUTS directory defined in feature.xml
        string strFileName = arrlstLayoutFilesToOverwrite[i].ToString();
        string strFilePath = properties.Definition.RootDirectory + "/LAYOUTS/" + strFileName;

        //check if file exists in HIVE
        string strFileInHive = SPUtility.GetGenericSetupPath(@"TEMPLATE\LAYOUTS") + "/" + strFileName;
        if (File.Exists(strFileInHive))
        {
            //rename file
            //copy new file
            try
            {
                //comment the following line if you dont want to save copies of previous pages
                File.Move(strFileInHive,Path.GetDirectoryName(strFileInHive) + "/" +  Path.GetFileNameWithoutExtension(strFileInHive) + "_" + DateTime.Now.ToString("ddMMyyyyhhmmss") + "_backup" + Path.GetExtension(strFileInHive));
                File.Copy(strFilePath, strFileInHive,true);
            }
            catch (Exception ex)
            {

            }
        }

    }


}