Thursday, July 16, 2015

Shredded Storage in SharePoint 2013 Explained

  • Shredded Storage is related to management of large binary objects i.e BLOBS
  • Shredded Storage is both improves I/O and reduces compute utilization when making incremental changes to document or storing documents in SharePoint 2013.
  • Shredded storage is built upon cobalt i.e. file synchronization via soap of http introduced in SP 2010
  • Shredded Storage is enabled by default and cannot be disabled.
  • In SP 2010 , shredded storage was used for communication between client and web server but whereas database is concerned whole file was fetched and saved after changes this is changed and shredded storage BLOBS are stored in database .



FileReadChunkSize

SharePoint 2010 introduced a new FileReadChunkSize property as a control associated with the BLOB cache which enabled a server farm administrator to control the size of incremental reads when a client requested a file.

FileWriteChunkSize


In SharePoint 2013 a new property loosely related to FileReadChunkSize is provided to allow control of the size of a shredded BLOB. 

Monday, May 25, 2015

How to fix Last run time issue in SharePoint 2013 Timer job

one of issues which developers frequently face while running Timer Job is Last run time: shows as N/A

this happens after we run Timer job with run now option also



How to fix this ?

1. open the Services using services.msc in run window
2. Restart "SharePoint Timer Service" and "SharePoint Administration" services


now navigate back to Job definition ( Central administration ---> Monitoring -->  Job Definition) and open the timer job , you will be able to see Last run value.


Have a great day !!

Wednesday, April 8, 2015

Programmatically adding watermark on PDF files in Sharepoint



This Blog will put some light on how to add watermark on PDF files from sharepoint document libraries and display selected in Iframe.

to achieve this we will be using itextsharp dll version 5.5.5.0 you can dowload it from here

steps to achieve PDFViewer with watermark
1. Create Visual Web Part name it according to your convenience

2. Add reference in your project to itextsharp dll

3. this is very important step don't forget to add itextsharp dll to GAC using gacutil or drag and drop feature

4. Now add two drop down control ,one iframe control and one submit button  in ascx page of visual webpart

first drop down will be used to bind names of document libraries
second will be used to select pdf files from selected document library

on click of submit button , Iframe will be used to display PDF file selected.

here is how ascx page looks like

<table style="width:100%; padding:2px;">

            <tr>
          <td class="auto-style1">Please select document libraries</td>
        <td class="auto-style1">
<asp:DropDownList ID="DocumentLibraries" runat="server" CssClass="auto-style2" AutoPostBack="true"  OnSelectedIndexChanged="DocumentLibraries_SelectedIndexChanged"></asp:DropDownList>
            </td>
    </tr>
    <tr>
        <td class="auto-style1">Please select PDF File to view</td>
        <td class="auto-style1">
<asp:DropDownList ID="pdffiles" runat="server" CssClass="auto-style2"></asp:DropDownList>
            </td>
    </tr>
    <tr>
        <td colspan="2">
            <asp:Button runat="server" ID="btnAggregrator" Text="Submit" onclick="btnAggregrator_Click"/>
        </td>
    </tr>

    </table>
<div>

<asp:Literal ID="l1" runat="server" ></asp:Literal>
</div>


5. In the ascx.cs file replace the page load method with below code

 protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                DocumentLibraries.Items.Clear();
                LoadDocumentLibraryDropdown();
            }
        }

6. Add new method as below

  private void LoadDocumentLibraryDropdown()
        {
                     SPWeb web = SPContext.Current.Web;
                 
                        DocumentLibraries.Items.Add("Please Select");
                        foreach (SPList libraries in web.Lists)
                        {
                            if (libraries.BaseType == SPBaseType.DocumentLibrary && libraries.BaseTemplate == SPListTemplateType.DocumentLibrary)
                            {
                                if (libraries.Title != "Form Templates" && libraries.Title != "Style Library" && libraries.Title != "Site Assets" && libraries.Title != "Site Collection Documents" && libraries.Title != "Translation Packages" && libraries.Title != "WaterMarkedDocuments")
                                {
                                    DocumentLibraries.Items.Add(libraries.Title);
                                }
                            }

                        }

7. Add the dropdown select index change as below

     protected void DocumentLibraries_SelectedIndexChanged(object sender, EventArgs e)
        {
         
                string documentLibrarySelected = DocumentLibraries.SelectedValue;
                if (documentLibrarySelected != "Please Select" && !string.IsNullOrEmpty(documentLibrarySelected))
                {

                             SPWeb web = SPContext.Current.Web;
                            SPDocumentLibrary library = (SPDocumentLibrary)web.Lists[documentLibrarySelected];
                            foreach (SPListItem files in library.Items)
                            {

                                if (files.File.Url.Contains(".pdf"))
                                {
                                    pdffiles.Items.Add(new System.Web.UI.WebControls.ListItem(files.File.Name, files.File.Url));

                                }                      
                    }              
                else
                {
                    pdffiles.Items.Clear();
                }
            }
}

8. Add Button click event

   protected void btnAggregrator_Click(object sender, EventArgs e)
        {
         
                string documentLibrarySelected = DocumentLibraries.SelectedValue;
                if (!string.IsNullOrEmpty(documentLibrarySelected))
                {
                    SPWeb web = SPContext.Current.Web;
                    SPWeb rootweb = SPContext.Current.Site.RootWeb;
                    SPList list = web.Lists[documentLibrarySelected];


                    SPFolder folder = rootweb.GetFolder(rootweb.Url + "/WaterMarkedDocuments");
                    if (folder.Exists == false)
                    {
                        rootweb.AllowUnsafeUpdates = true;
                        rootweb.Lists.Add("WaterMarkedDocuments", "library to store water arked documents", SPListTemplateType.DocumentLibrary);
                        rootweb.AllowUnsafeUpdates = false;
                        web.Update();
                        folder = rootweb.Folders["WaterMarkedDocuments"];

                    }

                    SPFile file = web.GetFile(pdffiles.SelectedValue);


                    SPUser currentUser = web.CurrentUser;
                    string watermark = null;
                    if (currentUser != null)
                        watermark = "Controlled Copy: " + SPContext.Current.Site.Url + "\\" + file.Title + "\\" + currentUser.Name + "\\" + System.DateTime.Now;

                    string url = web.Url + "/" + pdffiles.SelectedValue;

                    byte[] content = file.OpenBinary();


                    string newUrl = AddWaterMark(watermark, file, folder);


                    string modifiedUrl = rootweb.Url + "/WaterMarkedDocuments" + "/" + newUrl + "#toolbar=0&navpanes=0";

                    l1.Text = "<object id='AcrobatFrame' type='application/pdf' data='" + modifiedUrl + "' width='609' height='509'></object>";


                }
            }
9. add AddWaterMark event as below ( this method writes watermark over PDF files

 private string AddWaterMark(string watermarkText, SPFile file, SPFolder documentLibrayName)
        {
            string NewURL = string.Empty;
         
                SPFile fwatermarkfile = file;
             
                byte[] content = fwatermarkfile.OpenBinary();

                PdfReader pdfReader = new PdfReader(content);
                using (MemoryStream outputStream = new MemoryStream())
                using (PdfStamper pdfStamper = new PdfStamper(pdfReader, outputStream))
                {
                    for (int pageIndex = 1; pageIndex <= pdfReader.NumberOfPages; pageIndex++)
                    {
                        //Rectangle class in iText represent geometric representation...
                        //in this case, rectangle object would contain page geometry
                        Rectangle pageRectangle = pdfReader.GetPageSizeWithRotation(pageIndex);
                        //PdfContentByte object contains graphics and text content of page returned by PdfStamper
                        PdfContentByte pdfData = pdfStamper.GetUnderContent(pageIndex);
                        //create font size for watermark
                        pdfData.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 13);
                        //create new graphics state and assign opacity
                        PdfGState graphicsState = new PdfGState();
                        graphicsState.FillOpacity = 0.4F;
                        //set graphics state to PdfContentByte
                        pdfData.SetGState(graphicsState);
                        //indicates start of writing of text
                        pdfData.BeginText();
                        //show text as per position and rotation
                        pdfData.ShowTextAligned(Element.ALIGN_CENTER, watermarkText, pageRectangle.Width / 2, pageRectangle.Height / 44, 0);
                        //call endText to invalid font set
                        pdfData.EndText();
                    }
                    pdfStamper.Close();
                    content = outputStream.ToArray();
                    SPUser user = SPContext.Current.Web.CurrentUser;
                        NewURL = "WaterMarked" + file.Name;
                      documentLibrayName.Files.Add(NewURL, content,true);
                }
         
         
         
            return NewURL;
        }
    }
}


The above webpart will not modify the original pdf file it will copy the content of selected pdf file and it will create new pdf file with watermark in document library WaterMarkedDocuments ( code takes care of creating this document library .


if u have any doubts over this article please feel free to contact me over vishalkd@gmail.com. Happy coding !!

Saturday, March 21, 2015

Get multiple List data across multiple sites using SPSiteDataQuery in Sharepoint 2013


Scenario:  you want to display data from multiple list spread across multiple site inside the site collection.


Solution : SPSiteDataQuery to query across the site with web scoped at SiteCollection.


Example to explain this : 

Set Up :  

I have one site collection with two subsites

1. ProjectSubsite1 with List named as IssueList


Now i want to aggregate these two list data and display in web part on top level site collection , this cannot be possible with SPQuery hence we will be using SPSiteDataQuery as shown below 

Properties to set
1. Query :  you need to mention your condition in caml query format 
2. List : you need to mention List Servertemplate Id , hence data will be fetched from those list types
3. ViewFields : no of fields to be fetched for diplay
4. Webs : here you have to mention Site Collection so that search is triggered across complete site collection.

once SPSiteDataQuery object is formed pass the object to method web.GetSiteData this return datatable 

using (SPSite site = new SPSite(SPContext.Current.Site.Url))
{
using (SPWeb web = site.OpenWeb())
{
SPSiteDataQuery query = new SPSiteDataQuery();

query.Lists = "<Lists ServerTemplate=\"100\" />";

query.Query
= "<Where><Eq><FieldRef Name='ContentType' /><Value Type='Text'>IssueCT</Value></Eq></Where>";

query.ViewFields = "<FieldRef Name='Title' />";

query.Webs = "<Webs Scope=\"SiteCollection\" />"; 

DataTable dt = web.GetSiteData(query);

}
 }


Limitation : SPSiteDataQuery will run only across particular site collection.








Thursday, March 19, 2015

Thread was being aborted in sharepoint custom code


Thread was being aborted is one of the common error in custom code used to build web parts or any other solutions related to sharepoint , lets look into how i resolved it

If you want user to be redirected to new page or site and u are doing it in try catch block above error will be catch always but still user will be redirected to new URL.

ex :

Code : 


 try
            {
                // custom code to perform some action
                HttpContext.Current.Response.Redirect(RedirectURL);
            }
            catch (Exception ex)
            {
                // log the error to event to custom list
            }



Solution 1 : 

so avoid error please move Response.Redirect out of try catch as shown below 
// ***  Code *** //
 try
            {
                // custom code to perform some action
             
            }
            catch (Exception ex)
            {
                // log the error to event to custom list
            }
 HttpContext.Current.Response.Redirect(RedirectURL);

Solution 2 : 

if you cannot avoid using Response.Redirect  out of try catch block then add Response.Redirect with end response parameter set as false   HttpContext.Current.Response.Redirect(RedirectURL,false);



// ***  Code *** //
 try
            {
                // custom code to perform some action
                HttpContext.Current.Response.Redirect(RedirectURL,false);
            }
            catch (Exception ex)
            {
                // log the error to event to custom list
            }



I hope your doubts are clear else comment for further clarification

Saturday, February 7, 2015

sandbox solutions are deprecated in SharePoint 2013 ?

This blog will talk about why and what exactly is deprecated for sandbox solution in SharePoint 2013

Why
Sandbox solution had many disadvantages and if we see our SharePoint 2010 development we hardly looked sandbox solution as solution for most of our requirements
Few disadvantages of sandbox solutions:
  1. Limited access to object model
  2. Learning curve to understand the sandbox architecture
  3. Not easy to create proxy for full trusted code.

What
Many blogs says sandbox solution are deprecated yes its true but not completely
Sandbox solution containing only declarative things (like Web Templates and Design )
are still supported and not deprecated and sandbox solutions containing code is deprecated.
so if your solution doesn’t have code…consider the sandbox as solution.

Custom itemstyle.xsl for Content Query Webpart in SharePoint

While using Content Query Web Part its always best practice to use custom Item Style so here we will see how to create new templates in itemxsl style and change the reference in .webpart to custom item xsl style
1. Navigate to Style library –> XSL style sheets –> Itemstyle.xsl
And download the local copy .
2. ItemStyle.xsl contains different templates e.g. Default, NoImage, TitleOnly, TitleWithbackground etc,So to create custom ItemStyle.xsl , save ItemStyle.xsl as CustomItemStyle.xsl . Delete all the templates and add the new template with different name say HRDocs
<xsl:stylesheet
version=”1.0″
exclude-result-prefixes=”x d xsl msxsl cmswrt”
xmlns:x=”http://www.w3.org/2001/XMLSchema”
xmlns:d=”http://schemas.microsoft.com/sharepoint/dsp”
xmlns:cmswrt=”http://schemas.microsoft.com/WebParts/v3/Publishing/runtime”
xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” xmlns:msxsl=”urn:schemas-microsoft-com:xslt”>
<xsl:output method=”html”/>
<xsl:param name=”ItemsHaveStreams”>
<xsl:value-of select=”‘False’” />
</xsl:param>
<xsl:param name=”FeedTitle” />
<xsl:param name=”WPPropertyBinding-Title” />
<xsl:variable name=”OnClickTargetAttribute” select=”string(‘javascript:this.target=&quot;_blank&quot;’)” />
<xsl:variable name=”ImageWidth” />
<xsl:variable name=”ImageHeight” />
<xsl:template name=”HRDocs” match=”Row[@Style=HRDocs]” mode=”itemstyle”>
<xsl:variable name=”SafeLinkUrl”>
<xsl:call-template name=”OuterTemplate.GetSafeLink”>
<xsl:with-param name=”UrlColumnName” select=”‘LinkUrl’”/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name=”SafeImageUrl”>
<xsl:call-template name=”OuterTemplate.GetSafeStaticUrl”>
<xsl:with-param name=”UrlColumnName” select=”‘ImageUrl’”/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name=”DisplayTitle”>
<xsl:call-template name=”OuterTemplate.GetTitle”>
<xsl:with-param name=”Title” select=”@Title”/>
<xsl:with-param name=”UrlColumnName” select=”‘LinkUrl’”/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name=”LinkedInSafeImageUrl”>
<xsl:call-template name=”OuterTemplate.GetSafeLink”>
<xsl:with-param name=”UrlColumnName” select=”‘Linkedin’”/>
</xsl:call-template>
</xsl:variable>
<div>
<div>
<xsl:call-template name=”OuterTemplate.CallPresenceStatusIconTemplate”/> 
<div> 
<xsl:value-of select=”@documentname” />
</div>
<div>
<xsl:value-of select=”@docDescription” />
</div>
</div> </div> </xsl:template>
</xsl:stylesheet>
Things to take care while creating new template is to keep the same name for name and @style attributes( as below )
<xsl:template name=”HRDocs” match=”Row[@Style=HRDocs]“
and also add the <xsl:output method=”html”/> line  as added in above code to avoid the UI misalignement if any custom html is rendering null value.
3. Now upload this CustomItemStyle.xsl to same location ( Style Library –> XSL Style Sheets )
4. Now let’s make our CQWP to refer CustomItemStyle.xsl , open any page and add the CQWP and export the web part file which contains all the property tags , search for ItemXslLink
Which currently looks as
<property name=”ItemXslLink” type=”string”/>
Replace the above line with below
<property name=”ItemXslLink” type=”string”>/werkenbij/Style Library/XSL Style Sheets/CustomItemStyle.xsl</property>
Save the .webpart file as CustomCQWP.webpart and upload it to web part gallery [ Site Actions à Site Settings à Web parts (in Gallery)]
5. Add the web part on page , lets edit the web part to select the CustomItemStyle.xsl
Navigate to Presentation –>  Styles –>  Item Style and select CustomItemStyle.xsl from drop down.

That’s it guys your CQWP WITH CUSTOM Item style is ready to ship :)