Using SPGridView to bound to list data in SharePoint

These are the few points we need to remember while using SPGridView

With SPGridView we would inherit the same look and feel as the rest of SharePoint site because it makes use of the same CSS classes that the other grids in SharePoint use.

We need to set AutoGenerateColumns=false and explicitly bind the columns.

Create a new asp.net page

Put the following directive to use SPGridView

<%@ Register TagPrefix=”SharePoint” Namespace=”Microsoft.SharePoint.WebControls”

Assembly=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %

Declare the control

<SharePoint:SPGridView runat=”server” ID=”grdView”

  AutoGenerateColumns=”false” /> 

Declaring class level variable

public partial class _Default : System.Web.UI.Page

{

    // refer to your site collection

    SPSite mySite = new SPSite(@”http://d-1246:100&#8243;);

    // create class level spweb and splist object

    SPWeb myWeb;

    SPList myList;

Code for Page_Load EventHandler

protected void Page_Load(object sender, EventArgs e)

    {

        myWeb = mySite.OpenWeb();

        myList = myWeb.Lists[“ListName”];

        if (!Page.IsPostBack)

        {

            BindToGrid(myList, grdPropertyValues);

        }

    }

Code for BindToGrid method

private void BindToGrid(SPList myList, SPGridView gridView)

    {

        //grdView.Columns.Clear();

        // get all the listitem

        SPListItemCollection results = myList.Items;

        // create the datatable object

        DataTable table;

        table = new DataTable();

        table.Columns.Add(“Type”, typeof(string));

        table.Columns.Add(“Name”, typeof(string));

        table.Columns.Add(“Created”, typeof(string));    

        // Create rows for each splistitem

        DataRow row;       

        foreach (SPListItem result in results)

        {

            row = table.Rows.Add();

            row[“Type”] = result[“Type”].ToString();

            row[“Name”] = result[“Name”].ToString();

            row[“Created”] = result[“Created”].ToString();   

        }

        // create the bound fields

        SPBoundField boundField;

        boundField = new SPBoundField();

        boundField.HeaderText = “Type”;

        boundField.DataField = “Type”;

        boundField.ItemStyle.HorizontalAlign = HorizontalAlign.Center;

        boundField.ItemStyle.Wrap = false;

        gridView.Columns.Add(boundField);

 

 

        boundField = new SPBoundField();

        boundField.HeaderText = “Name”;

        boundField.DataField = “Name”;

        gridView.Columns.Add(boundField);

 

        boundField = new SPBoundField();

        boundField.HeaderText = “Created”;

        boundField.DataField = “Created”;

        gridView.Columns.Add(boundField);

       

        gridView.AutoGenerateColumns = false;

        gridView.DataSource = table.DefaultView;

        gridView.DataBind();  

    }

 

That’s it …

Advertisements

Gridview SelectedIndexChanged Showing no Data

It could happen if we are dynamically creating DataTable and bounding it to our GridView. Searching for it if found the following information on one of the blog

 

The GridView (and actually, all our data controls) does not save data items across postbacks.  This reduces ViewState (if the objects are even serializable) and enables garbage collection to happen and clean up your objects.  So, when you click the button to post back, the GridView has not called DataBind and therefore your data item isn’t there.  This is what you’ve discovered.

Selection is handled slightly differently than choosing an edit item, sorting, paging, or other functions: because those other functions require a change in the control tree or a query to the data source to get different data, they cause a DataBind to happen automatically at some point before the control renders again.  You can handle RowDataBound and get your data item.  Selection, however, doesn’t require new data or a different control tree (all that usually changes is the style properties on the row), so it will never call DataBind.  This makes selection very fast.  It also means you won’t get a DataBound or RowDataBound event unless you call DataBind yourself.  So you can’t use that event to get your data item unless you call it yourself.  If you need the data item, you can call DataBind yourself directly to get it, then handle OnRowDataBound, check the row index against the SelectedIndex, and get the data item.

However, this is kind of the shotgun method- it will get you what you want, but the performance has decreased because you’ve called DataBind again.  Also, if the data in the data store has been modified between your calls to databind, the row index that was the selected item may now point to a different row or just different data.  What data are you really looking for from the selected data item?  Is it just one or two fields?  If so, consider using DataKeyNames to store these fields, and then you can get to them via the DataKeys property.  If you don’t want to suffer the hit to ViewState from DataKeyNames, consider getting the data directly from the controls in the row of the GridView.

So I followed the suggestion highlighted in yellow and was able to retrieve the value for the selected row.

 

  protected void grdPropertyValues_SelectedIndexChanged(object sender, EventArgs e)

    {       

        GridViewRow row = grdPropertyValues.SelectedRow;

        // Get the selected row index

        iRownum = grdPropertyValues.SelectedIndex;

        // call the method that dynamically creates the DataTable and

        // bind the gridview to it

        BindConferenceDayToGrid(myList, grdPropertyValues);

    }

 

 

protected void grdPropertyValues_RowDataBound1(object sender, GridViewRowEventArgs e)

    {

        // getting the GridViewRow

        GridViewRow row = e.Row;

        // if RowType is DataRow and RowIndex is our selected row’s index

        if (e.Row.RowType == DataControlRowType.DataRow && row.RowIndex == iRownum)

        {       

                DataRowView drv = (DataRowView)e.Row.DataItem;

                Response.Write(“The value we need “+drv.Row[1].ToString());          

        }      

    }

 

That’s it ..

 

 

 

Updating account record using Oracle\Siebel CRM On Demand Web Service in .NET

 

To update the Account record we need to first add web reference to the account.wsdl.

 

Than can make use of AccountUpdate method of Account Entity.

 

  // Login to the CRM server

            string loginUrlString = https://servername/Services/Integration?command=login&#8221;;

            // Get the valid Session id to be appended for each subsequent request

            String sessionID = ManageSession.Login(loginUrlString, @”orgname/username”, “password”);

            try

            {

                // Download the account wsdl from the Admin section of the CRM application

                // Add web reference to the wsdl

                // Create the instance of the opportunity entity

                Account myAcc = new Account();

                myAcc.Url = https://secure-ausomxapa.crmondemand.com/Services/Integration;jsessionid=&#8221; + sessionID;               

                // Create the instance of Account Data

                AccountData[] myAccData = new AccountData[1];

                myAccData[0] = new AccountData();

                // the order number to be updated

                myAccData[0].stOrder_Number = “orderNumber”;

                // the id of the account to be updated

                myAccData[0].Id = “orderID”;

                // creating ListOfAccountData object

                ListOfAccountData myLstOfAcctData = new ListOfAccountData();

                myLstOfAcctData.Account = myAccData;

                // using AccountUpdate_Input

                AccountUpdate_Input myAccUpdateInput = new AccountUpdate_Input();

                myAccUpdateInput.ListOfAccount = myLstOfAcctData;

                // using account’s Accout Update method to update the record               

                AccountUpdate_Output myAccntUpdateOutput = myAcc.AccountUpdate(myAccUpdateInput);

            }

            catch (SoapException ex)

            {

            }

            catch (Exception ex)

            {

            }

 

 

That’s it …

Using Oracle CRM On Demand Web Service to query Opportunity Data in .NET

1) Create a windows application

2) Put the following code in the form load event handler

 

Explaination is put in as comment

 

 

private void Form1_Load(object sender, EventArgs e)

        {         

            // Login to the CRM server

            string loginUrlString = https://servername/Services/Integration?command=login&#8221;;          

            // Get the valid Session id to be appended for each subsequent request

            String sessionID = ManageSession.Login(loginUrlString, @”orgname/username”, “pwd”);

 

            try

            {

                // Download the opportunity wsdl from the Admin section of the CRM application

                // Add web reference to the wsdl

                // Create the instance of the opportunity entity

                Opportunity myOpp = new Opportunity();

                myOpp.Url = https://servername/Services/Integration;jsessionid=&#8221; + sessionID;

                // Set the query

                // To find the record with sales stage as closed/won

                queryType mySalesStage = new queryType();

                mySalesStage.Value = “LIKE ‘Closed/Won'”;

                // Values needed back from the server

                // 1) Purchase Order Date

                queryType myPODate = new queryType();

                myPODate.Value  = “”;

                // 2) Purchase Order Number

                queryType myPONumber = new queryType();

                myPONumber.Value  = “”;

                // 2) Opportunity Name

                queryType myOppName=new queryType();

                myOppName.Value=“”;   

               

                // Create opportunityquery instance and set the appropriate parameters

                OpportunityQuery myOppQuery = new OpportunityQuery();

                myOppQuery.SalesStage = mySalesStage;

                myOppQuery.dtPurchase_Order_Date = myPODate;

                myOppQuery.stPurchase_Order_No = myPONumber;

                myOppQuery.OpportunityName = myOppName;

 

                // Set ListOfOpportunityQuery

                ListOfOpportunityQuery lstOfOppQuery = new ListOfOpportunityQuery();

                lstOfOppQuery.Opportunity = myOppQuery;

                // Number of records to fetch

                lstOfOppQuery.pagesize = “100”;

 

                // set OpportunityQueryPage_Input

                OpportunityQueryPage_Input myOppInput = new OpportunityQueryPage_Input();

                myOppInput.ListOfOpportunity = lstOfOppQuery;

               

                // Get the output

                OpportunityQueryPage_Output myOutput = myOpp.OpportunityQueryPage(myOppInput);

 

                // Get ListOfOpportunityData

                ListOfOpportunityData myOppData = myOutput.ListOfOpportunity;

                OpportunityData[] oppData = myOppData.Opportunity;

                // Total number of records returned

                MessageBox.Show(oppData.GetLength(0).ToString());

 

                foreach(OpportunityData oData in oppData)

                {

                    MessageBox.Show(“Opportunity Name :-“ + oData.OpportunityName

                        + “, Opp PO Date =” + oData.dtPurchase_Order_Date.ToShortDateString()

                        + ” Opp PO Number =” + oData.stPurchase_Order_No);                 

 

                }

   }

            catch (SoapException ex)

            {

                MessageBox.Show(ex.Detail.InnerXml);

            }

 

 

The code for ManageSession.Login static mehtod

 

public static String Login(String loginUrlString, String userName, String password)

        {

        try

        {

            // create a http request and set the headers for authentication

            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(loginUrlString);

            HttpWebResponse myResponse;

            myRequest.Method = “POST”;

            // passing username and password in the http header

            // username format if it includes slash should be the forward slash /

            myRequest.Headers[“UserName”] = userName;

            myRequest.Headers[“Password”] = password;          

            myResponse = (HttpWebResponse)myRequest.GetResponse();

            Stream sr = myResponse.GetResponseStream();

            // retrieve session id

            char[] sep = { ‘;’ };

            String[] headers = myResponse.Headers[“Set-Cookie”].Split(sep);

            for (int i=0; i <= headers.Length-1; i++)

            {

            if (headers[i].StartsWith(“JSESSIONID”))

            {

            sep[0] = ‘=’;

            SessionID = headers[i].Split(sep)[1];

            break;

            }

            }

            sr.Close();

            myResponse.Close();

        }

        catch (WebException webException)

        {

           

        }

        catch (Exception ex)

        {

        }

        // send back the session id that should be passed to subsequent calls

        // to webservices

        return SessionID;       

        }

 

That’s it …

Adding a Read Only Field or Read Only Column to a SharePoint List

We had a requirement to add a read only column to one of our document library. Using Create column it isn’t possible to add a read only column.  One option could be to create the new column and then using SharePoint designer we can make use of JavaScript and modify the NewForm.aspx and EditForm.aspx to display that field as read only.

We thought of adding it as a Site Column making use of ReadOnly property of field.

<?xml version=1.0 encoding=utf-8?>

<Elements xmlns=http://schemas.microsoft.com/sharepoint/>

                <Field ID={0B8A5574-80BF-4d5e-99B9-9A25D8E8D21E}

                                   Name=_IsApproved

                                   DisplayName=Is Document Approved?

                                   Group=Custom Columns

                                   Type=Text                      

                                   Required=FALSE      

                                   ReadOnly=TRUE       

                                 

                                   >

                </Field>            

</Elements>

However if we set ReadOnly as True the field doesn’t appear on Site Settings pages for managaing site columns and content types. However we can add it to the view using the below code

 

SPSite oSiteCollection = new SPSite(@”http://servername:port&#8221;);

            using (SPWeb oWebsite = oSiteCollection.OpenWeb())

            {

                SPList oList = oWebsite.Lists[“ListName”];

                oList.Fields.Add(“Is Document Approved?”, SPFieldType.Text, false);

                oList.Update();

                SPView oView = oList.DefaultView;

                oView.ViewFields.Add(“Is Document Approved?”);             

                oView.Update();

                }

However the field was still appearing in editform.aspx and newform.aspx in editable mode.         

So finally tried this

Modified the definition for the custom site column as following

<?xml version=1.0 encoding=utf-8?>

<Elements xmlns=http://schemas.microsoft.com/sharepoint/>

                <Field ID={0B8A5574-80BF-4d5e-99B9-9A25D8E8D21E}

                                   Name=_IsApproved

                                   DisplayName=Is Document Approved?

                                   Group=Custom Columns

                                   Type=Text                      

                                   Required=FALSE      

                                   ReadOnly=FALSE

                                   ShowInDisplayForm=TRUE

                                   ShowInEditForm=FALSE

                                   ShowInNewForm=FALSE                        

                                   >

                </Field>            

</Elements>

 

Setting ShowInDisplayForm and ShowInEditForm as False and keeping ReadOnly as False so that the field could appear within Site Settings pages for managing site columns.

This last solution worked ..

The feature file for installing the above site column

<?xml version=1.0 encoding=utf-8?>

<Feature  Id=D829F71B-7FCC-4f0d-950D-6B562AFF400E

          Title=MyCustom Feature

          Description=This is my custom column feature

          Version=12.0.0.0

          Scope=Site

          xmlns=http://schemas.microsoft.com/sharepoint/>

                <ElementManifests>

                                <ElementManifest Location=MyCustomColumn.xml />                          

                </ElementManifests>  

</Feature>

 

Now the only way to edit the column was through SharePoint Object Model

   SPSite oSiteCollection = new SPSite(@”http://servername:port&#8221;);

            using (SPWeb oWebsite = oSiteCollection.OpenWeb())

            {

                SPList oList = oWebsite.Lists[“ListName”];        

                SPListItem item = oList.Items[0];         

                item[“Is Document Approved?”] = “These are my changes”;

                item.Update();              

            }

That’s it..

Adding custom menu and button to custom entity through ISV.CONFIG

To add custom menu and button to Entity form,

Go to Customizations-Export Customizations-Select ISV.CONFIG.

Open the customizations.xml file and add the following xml tags to it

<Entity name=new_customentity>

          <MenuBar>

            <CustomMenus>

              <Menu>

                <Titles>

                  <Title LCID=1033 Text=My Custom Menu>

                  </Title>

                </Titles>

                <MenuItem Url=http://www.microsoft.com PassParams=0 WinMode=1>

                  <Titles>

                    <Title LCID=1033 Text=Coming Soon ..>

                    </Title>

                  </Titles>

                </MenuItem>

              </Menu>

            </CustomMenus>

          </MenuBar>

          <ToolBar>

            <Button AvailableOffline=false ValidForCreate=1 ValidForUpdate=1 Url=http://www.google.co.in>

              <Titles>

                <Title LCID=1033 Text=My Custom Button… />

              </Titles>

              <ToolTips>

                <ToolTip

                 LCID=1033

                 Text=My custom button tooltip     />

              </ToolTips>

            </Button>

          </ToolBar>

        </Entity>

That’s it ..

Using Siebel CRM On Demand Web Services in Microsoft.NET

1) Create a new windows application.

2) Put the following code in the form load

private void Form1_Load(object sender, EventArgs e)

{

string loginUrlString = https://servername/Services/Integration?command=login&#8221;;

String sessionID = ManageSession.Login(loginUrlString, @”orgname-devusername”, “password”);

}

3) Define the login method within ManageSession class in the following manner


public static string SessionID = “”;

public static String Login(String loginUrlString, String userName, String password)

{

try

{

// create a http request and set the headers for authentication

HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(loginUrlString);

HttpWebResponse myResponse;

myRequest.Method = “POST”;

// passing username and password in the http header

// username format if it includes slash should be the forward slash /

myRequest.Headers[“UserName”] = userName;

myRequest.Headers[“Password”] = password;

myResponse = (HttpWebResponse)myRequest.GetResponse();

Stream sr = myResponse.GetResponseStream();

// retrieve session id

char[] sep = { ‘;’ };

String[] headers = myResponse.Headers[“Set-Cookie”].Split(sep);

for (int i=0; i <= headers.Length-1; i++)

{

if (headers[i].StartsWith(“JSESSIONID”))

{

sep[0] = ‘=’;

SessionID = headers[i].Split(sep)[1];

break;

}

}

sr.Close();

myResponse.Close();

}

catch (WebException webException)

{

}

catch (Exception ex)

{

}

// send back the session id that should be passed to subsequent calls

// to webservices

return SessionID;

}

That’s it..

The remote server returned an error: (500) Internal Server Error while using Siebel CRM On Demand Web Services.

I got this error while trying to Logging In to the Web Services Session using .NET. Spent whole day for finding out what could be the reason behind the issue. Finally came to know the issue was because of the username being not passed correctly.

 

The username that we were passing was in this particular format that we would normally do

 

 ‘orgname-devusername’

 

Whereas it was expecting it in this format

 

‘orgname-dev/username’

 

i.e. forward slash instead of the back slash.

 

I hope it helps!

Customizing Custom Web Part Menu in SharePoint

Any standard web part within SharePoint would have menu options like Minimize, Close, and Modify Shared Web Part. We can even add our own custom menu options over there. They are referred to as verbs in web part’s context. We could add three types of web part menu verbs.

Client Side –We could specify JavaScript over here.

Server Side – We can attach event handler over here.

Both – We could have both JavaScript and event handler specified.

Let’s take a simple example where we would be adding all the above three kind of verbs.

Create a web part project within Visual Studio.

Put the following code for web part,

It would have a text box that would show the text set using the event handler specified in the server side verb.

[Guid(“172bc4c1-1c5d-49cd-93bc-1874acbbb9c8”)]

    public class WebPartMenuVerbWebPart : System.Web.UI.WebControls.WebParts.WebPart

    {

        public WebPartMenuVerbWebPart()

        {

        }

 

        protected  TextBox txtInfo;

        protected override void CreateChildControls()

        {           

            txtInfo = new TextBox();

            this.Controls.Add(txtInfo);           

        }

        public override WebPartVerbCollection Verbs

        {

            get

            {

                // Client side verb

                WebPartVerb clientSideVerb = new WebPartVerb(“clientID”, “javascript:alert(‘Hello World from Java Script Verb!’);”);

                clientSideVerb.Text = “Client Side Verb”;

                // Server side verb

                WebPartVerb serverSideVerb = new WebPartVerb(“serverID”, new WebPartEventHandler(ServerVerbEventHandler));

                serverSideVerb.Text = “Server Side Verb”;

                // Verb for both client side and server side

                WebPartVerb bothSideVerb = new WebPartVerb(“bothID”, new WebPartEventHandler(ServerVerbEventHandler), “javascript:alert(‘Hello World from Java Script Verb!’);”);

                bothSideVerb.Text = “Both Side Verb”;          

                WebPartVerbCollection wbVerbCollection = new WebPartVerbCollection(base.Verbs, new WebPartVerb[] { clientSideVerb, serverSideVerb, bothSideVerb  });

                return wbVerbCollection;

            }

        }

        protected void ServerVerbEventHandler(object sender, WebPartEventArgs args)

        {

            txtInfo.Text=“Hello world from Server Side Verb”;                           

        }       

    }

 

That’s it …

Fixing SQL Server Error : The backup set holds a backup of database other than the existing database.

We faced this error while restoring a database in Sql Server using the .bak(backup)  file but into a different database.

The way it was resolved for us was to

1) Selecting Options within Restore Database dialog box.

2) Specifying correct path to the mdf and log file for the database.

3) Checking Overwrite the existing database option.

That’ s it ..