Thursday, August 27, 2015

Understand the "AllowUnsafeUpdates", and use it to it best way


The Best way Deal  to deal with AllowUnsafeUpdates:

Source Url:  https://hristopavlov.wordpress.com/2008/05/16/what-you-need-to-know-about-allowunsafeupdates/
-----------------------------------------------------------------------------------------------------------

1) Don’t update SharePoint objects from your code behind on GET requests as if you do so your code will be exploitable via a cross-site scripting. If you understand the consequences of doing this and still want to do it then read below about how to use the AllowUnsafeUpdates property.
2) If your code is processing a POST request then make sure you call SPUtility.ValidateFormDigest() before you do anything else. This will ensure that the post request is validated (that it is not a cross-site scripting attack) and after that you will not have to worry about AllowUnsafeUpdates, because its default value will be “true” after the form digest is validated. 

The Microsoft idea behind introducing the AllowUnsafeUpdates property is to protect YOU from cross-site scripting attacks. The way this works is that if your application is running in an HTTPContext (i.e. it’s a web part for instance) and the request is a GET request then SharePoint will refuse to do any changes unless the value ofAllowUnsafeUpdates is set to true and by default it will be false for GET requests. If you try to do any updates to lists, webs or any SharePoint objects that require an SPSite to be created first, and if you don’t set AllowUnsafeUpdates to true you will get this exception:
System.Exception: Microsoft.SharePoint.SPException: The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again. —> System.Runtime.InteropServices.COMException (0x8102006D): The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again.
It is important to understand that if you are writing a class library for example, your code will behave differently when called from a web application and when called from a rich client. Actually if the HTTPContext.Current is null then AllowSafeUpdates will be always true. This is the case in rich clients where no cross-scripting is possible as there are simply no web requests.
Usually when you create your own SPSite or SPWeb objects, i.e. when you are not getting them from the SPContext (such as SPContext.Web), and when you try to update anything such as web or list properties, list items metadata etc, you may get the exception listed above. This is a clear indication that AllowUnsafeUpdates of the SPWeb is false and this is preventing you from doing the update. This problem is resolved easily by setting the AllowUnsafeUpdates of the parent web object to true. Still sometimes even after you have done this you may still be getting the same error.  This is typically caused by one of the the following reasons:
A) You have set the AllowUnsafeUpdate to true for the wrong SPWeb
You have to be careful because sometimes the ParentWeb of an object is not the same instance of the web you have retrieved the object from. For example when you goinitialWeb.Lists[listId] you would expect that the returned list’s ParentWeb instance is the same as you initialWeb. However this is not the case. So if somewhere later in your code you go list.ParentWeb.UpdateSomething() this will not work because you have never set the AllowUnsafeUpdates property of list.ParentWeb. You have set it for your initialWeb but even that this is the same web as the list’s parent web both are different instances. Usually you see the error and then you go and investigate in Reflector whether this is the same instance or not. Alternatively you could use another more generic and clever way to deal with almost any similar situation described in the following post:
The author suggests that you can set the HttpContent.Current to null before you do your updates and then reassign its initial preserved value when done. This will work great but remember to set the HTTPContent to null as early as possible. In the post above probably SharePoint uses the site.RootWeb to do the updates to the site scoped features and the RootWeb’s AllowUnsafeUpdates hasn’t been set to true explicitly.
B) The AllowUnsafeUpdates gets reset to false sometimes after you have set it to true
If we have a look at how the property is managed it turns out that it is stored in the request object associated with every SPWeb (which is actually a COM object)
[SharePointPermission(SecurityAction.Demand, UnsafeSaveOnGet = true)]
private void SetAllowUnsafeUpdates(bool allowUnsafeUpdates)
{
     this.Request.SetIgnoreCanary(allowUnsafeUpdates);
}
This actually means that every time the request is reset, the property will be also reset to its default value. The m_Request member is modified when a new web is created, when the web is disposed or when the SPWeb.Invalidate() method is called.
internal void Invalidate()
{
   if (this.m_Request != null)
   {
      if (this.m_RequestOwnedByThisWeb)
      {
         SPRequestManager.Release(this.m_Request);
      }

      this.m_Request = null;
   }

   this.m_bInited = false;
   this.m_bPublicPropertiesInited = false;
   this.m_Url = null;
}
So any operation that calls SPWeb.Invalidate() will reset AllowUnsafeUpdate to its default value. And for code running under HTTPContext, i.e. web applications, this default value for a GET request will be false. I’ve looked up for you all legitimate cases for which Invalidate() is being called by the SharePoint object model. These cases are:
1) When the Name or the ServerRelativeUrl properties of the SPWeb are changed and then Update() is called. In this case the AllowUnsafeUpdate is reset because with the change of these properties the URL of the web will change and logically the request object will change as it will now point to a different URL.
2) When any object that implements ISecurable (those are SPWeb, SPList and SPListItem) breaks or reverts their role definition inheritance. This means every time you callSPRoleDefinitionCollection.BreakInheritance(), BreakRoleInheritance(), ResetRoleInheritance() or set the value of HasUniquePerm the AllowUnsafeUpdatesproperty of the parent web will reset to its default value and you may need to set it back to true in order to do further updates to the same objects.
3) In many cases when an exception is caught by the SharePoint object model when you try to retrieve any sort of data the AllowUnsafeUpdates of the parent web will be reset to false as a precaution to protect against potential exploits. In those cases however the objects will be in unknown state anyway after the request has been reset and the exception is re-thrown so they are of no practical interest.
And finally it is also good to mention that you may get another related exception when trying to update your SharePoint objects and that is:
System.Exception: Microsoft.SharePoint.SPException: Cannot complete this action.Please try again. —> System.Runtime.InteropServices.COMException (0x80004005): Cannot complete this action.
This usually happens when some updates have been made to an object (usually SPSite, SPWeb or SPList) that may be clashing with your changes and SharePoint refuses to do the update. To recover from this situation you simply need to create fresh copies of the SPSite and the SPWeb objects and do the updates on the objects retrieved from the fresh copies. And of course don’t forget to set the AllowUnsafeUpdates to true for the freshly created SPWeb if required.

Sunday, June 14, 2015

Converting image byte array to image control directly


**********************************************************
private void GetUserPhoto(int id)
        {
            try
            {
                LookUps obj = new LookUps();
                List<UserPhotoEntity> newObj = obj.GetPhotoById(id);
                Byte[] photoByte = newObj[0].Photo;
                ImageConverter ic = new ImageConverter();
                System.Drawing.Image img = (System.Drawing.Image)ic.ConvertFrom(photoByte);
               // Image1.ImageUrl = "data:image/jpg;base64," + Convert.ToBase64String((byte[])photoByte);
                Image1.ImageUrl ="data:image/jpg;base64," + Convert.ToBase64String((byte[])photoByte);


                //Response.ClearHeaders();
                //Response.ContentType = "image/JPEG";
                //Response.AddHeader("content-disposition", "inline;filename=Photo.jpeg");
                //Response.BinaryWrite(photoByte);
            }
            catch (Exception ex)
            {
                ex.ToString();
            }
**************************************************************

Checklist for coding in c# for SharePoint Development

Checklist for SharePoint Development


·         Does my code properly dispose of SharePoint objects?
·         Does my code cache objects properly?
·         Does my code cache the correct types of objects?
·         Does my code use thread synchronization when necessary?
·         Does my code work as efficiently for 1,000 users as it does for 10 users?
·         Code should not include hardcoding of any type

Naming Conventions

·         Coding should follow a proper naming conventions, either Camel or Pascal casing, use PascalCasing for class names and method names. use camelCasing for method arguments and local variables
·         Make sure to not to use underscores in identifiers. Exception: you can prefix private static variables with an underscore.
·         Make sure to use noun or noun phrases to name a class
·         Prefix interfaces with the letter I.  Interface names are noun (phrases) or adjectives.
·         organize namespaces with a clearly defined structure
o   // Examples
o   namespace Company.Product.Module.SubModule
o   namespace Product.Module.Component
o   namespace Product.Layer.Module.Group
·         do not use Hungarian notation or any other type identification in identifiers
·         // Correct
·         int counter;
·         string name;
·          
·         // Avoid
·         int iCounter;
·         string strName;

·         Controls Naming Convention:-
o   Textbox: txtName
o   Button: btnName
o   Label: lblName
o   Panel: pnlViewer
o   Image: imgName
Properties:s
o   Use noun or noun phrase with Pascal case like UserID, Password etc.
Methods:
o   Use verb or verb phrase with Pascal case like InsertQuery(), GetUserInfo() etc.

Coding Flow and Comment

·         Write only one statement per line.
·         Write only one declaration per line.
·         Add at least one blank line between method definitions and property definitions.
·         Place the comment on a separate line, not at the end of a line of code.
·         Begin comment text with an uppercase letter.
·         End comment text with a period.
·         Insert one space between the comment delimiter (//) and the comment text
·         Do not create formatted blocks of asterisks around comments.
·         Either use Camel case like userID or Pascal case like UserID

Object Model

·         Make sure SharePoint objects like SPSite and SPWeb are being disposed properly. Do not.Site or dispose of any item returned directly from the Microsoft.SharePoint.SPContext Microsoft.SharePoint.SPContext.Web property except when you obtain reference to these using a constructor or when you use AllWebs.
  • The SPSiteCollection.Add method creates and returns a new SPSite object. You should dispose of any SPSite object returned from the SPSiteCollection.Add method.
  • The SPSiteCollection [] index operator returns a new SPSite object for each access. An SPSiteinstance is created even if that object was already accessed. The following code samples demonstrate improper disposal of the SPSite object.
  • The SPSite.AllWebs.Add method creates and returns an SPWeb object. You should dispose of anySPWeb object returned from SPSite.AllWebs.Add.
  • The SPWebCollection.Add method creates and returns an SPWeb object that needs to be disposed.
  • The SPSite.AllWebs [] index operator returns a new SPWeb instance each time it is accessed.
  • The OpenWeb method and SelfServiceCreateSite method (all signatures) create an SPWeb object and return it to the caller.
·         The Microsoft.Office.Server.UserProfiles.PersonalSite returns an SPSite object that must be disposed

  • The SPWeb.Webs property returns an SPWebCollection object. The SPWeb objects in this collection must be disposed.
  • The SPWeb.Webs.Add method (or Add) creates and returns a new SPWeb object. You should dispose of any SPWeb object returned from this method call.
  • The SPWeb.Webs[] index operator returns a new SPWeb object for each access

Using Objects in Event Receivers

Do not instantiate SPWeb, SPSite, SPList, or SPListItem objects within an event receiver. Event receivers that instantiate SPSite, SPWeb, SPList, or SPListItem objects instead of using the instances passed via the event properties can cause the following problems:
  • They incur significant additional roundtrips to the database. (One write operation can result in up to five additional roundtrips in each event receiver.)
Calling the Update method on these instances can cause subsequent Update calls in other registered event receivers to fail.


  • Do not use an unbounded SPQuery object.
  • An SPQuery object without a value for RowLimit will perform poorly and fail on large lists. Specify aRowLimit between 1 and 2000 and, if necessary, page through the list.
  • Use indexed fields.
  • If you query on a field that is not indexed, the query will be blocked whenever it would result in a scan of more items than the query threshold (as soon as there are more items in the list than are specified in the query threshold). Set SPQuery.RowLimit to a value that is less than the query threshold.
  • If you know the URL of your list item and want to query by FileRef, use SPWeb.GetListItem(stringstrUrl, string field1, params string[] fields) instead.

Exception Handling

·         Make sure to use Try-catch and using statements in exception-handling
·         Don't catch (Exception) more than once per thread
·         Cleanup code should be put in finally blocks
·         Don't use exception handling as means of returning information from a method
·         Errors/Exceptions must be logged



·         Switching ON and OFF the AllowUnsafeUpdates option, as and when appropriately.
·         Disposing the SPSite objects after usage.
·         Disposing the SPWeb objects after usage.
·         Avoid disposing objects derived from SPContext.
·         Try the "Using" clause - to avoid the overhead of disposing objects explicitly.

Customization

·         Don't change any default SharePoint installation files
·         Custom master pages will be based on a copy of the default master page
·         Avoid customising content pages with SharePoint Designer
·         Avoid inline server side script in pages
·         All applications should be globalised and then localised to English
·         Package all web parts and templates as features




Deploy code 
Deploy code using wsp solutions. Ensure code is not in debug mode when compiled, it runs slower and potentially can crash/holdup your production environment. Implement CAS, deploy to bins if possible and apply CAS security policies to custom coding.

Configuration

·         In a shared environment no AppSetting entries are generally allowed in the web.config configuration file of WSS. Instead consider using your own application specific configuration file and store along within your application or feature folder. The feature.xml file should be used for storing Feature properties. A SharePoint list can be considered for storing common configuration data

Features:-

·         All Feature scope should be Site collection scope or lower instead of at the Web-application level. If features can be re-used then they could be deployed at the web-application level.
·         Feature Title should be appropriately named.
·         Provide full description which should include information on the usage, any restrictions, and dependencies on other features, assembly, ownership and contact information. This description should be included in the Feature.xml in addition to any documentation


Attach multiple file through the File upload control and attach to SharePoint list item on save



Uploading multiple files on save button to SharePoint  List Item 

Attachment Related tasks

File Upload Event
**************************************************************************
public void UploadButton_onClick(object sender, EventArgs e))
{
                     DataTable fileDt =new DataTable ();
                     DataRow row=null;
                     fileDt = GetFileTable();  
                     row = fileDt.NewRow();
                     row["Id"] = attachmentId;
                     row["FileName"] = fileAttachmentUpload.FileName;
                     row["FilePath"] = "";
                     row["FileContent"] = GetFileStream();  // This is File Byte stream
                     fileDt.Rows.Add(row);
                     ViewState["FilesList"] = fileDt;
}

Breaking the file in File Stream. and return the Byte array
************************ **************************************************
        /// <summary>
        /// Returning Files in byte [] array after reading by stream
        /// </summary>
        /// <returns></returns>
        public byte[] GetFileStream()
        {
            byte[] contents = null;
            try
            {
                Stream fStream = fileAttachmentUpload.PostedFile.InputStream;
                contents = new byte[fStream.Length];
                fStream.Read(contents, 0, (int)fStream.Length);
                fStream.Close();
            }
            catch (Exception ex)
            {
                errorLog.LogEntery(ex);
            }
            return contents;
        }

Attaching the files to SharePoint ListItem *************************************************************************
/// <summary>
        /// Adding Attachment Files To SharePoint ListItem
        /// </summary>
        /// <param name="Item"></param>
        public void AddAttachmentToList(SPListItem Item)
        {
            DataTable dt = null;
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    SPWeb web = SPContext.Current.Web;
                    if (ViewState["FilesList"] != null)
                    {
                        dt = (DataTable)ViewState["FilesList"];
                        foreach (DataRow row in dt.Rows)
                        {
                            byte[] fs = (byte[])row["FileContent"];
                            string fileName = (string)row["FileName"];
                             SPAttachmentCollection attachments = Item.Attachments;
                            attachments.Add(fileName, fs);
                           }
                    }
                    web.AllowUnsafeUpdates = true;
                    taskItem.Update();
                    web.AllowUnsafeUpdates = false;
                });
            }
            catch (Exception ex)
            {
                errorLog.LogEntery(ex);
            }

        }

Getting All Attachment from ListItem
************************************************************************

/// Getting all attachment from a listitem with fileName and its file url and return in Hashtable

public Hashtable GetListAttachemnts(SPListItem taskItem)
        {
            Hashtable _listItems = new Hashtable();
            try
            {

                SPAttachmentCollection attachments = taskItem.Attachments;

                foreach (var attachment in attachments)
                {
                    string attachmentAbsoluteURL = taskItem.Attachments.UrlPrefix + attachment;
                    _listItems.Add(attachment, attachmentAbsoluteURL);

                }
            }
            catch (Exception ex)
            {
                errorLog.LogEntery(ex);
            }
            return _listItems;
        }