Showing posts with label SharePoint. Show all posts
Showing posts with label SharePoint. Show all posts

Saturday, August 14, 2010

Set Account As SharePoint System Account


In my previous two post related to SharePoint System Account i explain how to display you custom “DOMAIN/<<UserName>>” instead of “System Account”. But in this post i am going to explain different thing opposite to previous post.

Previous Posts : Post1 Post2

There are two way to achieve this thing.

1. Go To Central Admin Site
2. Security –> Configure Service Accounts
image
3. Select your application pool
4. then Select an account for this component (Select your account)
image

If your account is not already register as manage account then click on “Register new managed account”.
image
Another way to do same thing is

1. Go To Central Administration.
2. Click Application Management
3. Click Manage Web Application
4. Choose your web application
image
5. Click on “User Policy”
6. When “Policy for Web Application” popup open click on “Add User”
image

7. Click next
image

8. In this add users for which you want to display that account as “System Account”. Make sure you have “Account operates as system” checkbox selected.
image 

Let me know your comment and view on this.

SharePoint/System Account Settings


In my previous post about SharePoint system account, i explain that how to configure account so that you can see your DOMAIN/<<UserName>> account as System Account.

But to do so you need SharePoint Central Administrator site permission. There is another way to do same thing using coding. ( Little bit trick :))

There is hidden List called “User Information List” in SharePoint site.You can find system account and update that listitem for “System Account”.

1. (Before Update Item)
image
2. Custom code to update item.

image

3.  In above code you can replace “your name” with your desired name.
4. After you can see in profile and Upper Right corner of your site.
image 

You can customize any account using above code. Sometime you want friendly name instead DOMAIN\<<UserName>>

Let me know your comment on this.

SharePoint System Account Issue


SharePoint\System account is special account. Sometime it happens that when you login using DOMAIN/<<UserName>> is display as “System Account”. (Following image)

 image

This is because of when application created or extended, during that time which account specify for application pool identity that consider as “SharePoint/System” account.

But if you want to display your username instead of “System Account” following are the solutions for that.

1. Go to Central Administration Site
2. Go to Security –> Configure Service Account
image
3. Next page you can see that “Credential Management”.
image
4. Select your application pool.
5. Select different account. (Other than your account). Which ever account you specify over here for that you can see “SharePoint/System” account.
6. If you still want that your application pool identity should be your name then manually set using IIS Manager.

Let me know if you still have any question about it.

Saturday, June 6, 2009

DateTime operation in .NET Application

DateTime is a very important datatype and data in terms of realtime application. Some of the application that run timely manner and some of the application that generate data (log file) with time.
To generate such report you need to required store information about date and time.

In .NET there is datatype called DateTime. This contain all information about datetime but sometime problem with this too.

For example:

DateTime dt = DateTime.Now;  // 6/6/2009 09:35:00 PM.
This is used to get current current time of system. If you store this time in file or in a database and later you retrieve then you get that time. So at last “6/6/2009 09:35:00 PM” this is going to  store in a file.

Problem occur when you retrieve this later to display information and by some reason you make changes to current time zone of system or sometime timezone of application. So then also you get “6/6/2009 09:35:00 PM.” as data , which is not right.

So best way to store date is UTC format.

DateTime dt = DateTime.UtcNow and after retrieval convert it to LocalTime but for that also you have to confirm that stored DateTime is in Utc format.

DateTime structure contains  methods called ToBinary() and FromBinary().

long binaryDate  = DateTime.Now.ToBinary() ;

Now store ‘binaryDate’ value in database or text file. So later when you get this value.

DateTime dt =  DateTime.FromBinary(binaryDate).  This will generate correct Date and Time even after timezone changed. This is because of binaryDate( Long ) value contain information about TimeZone too. So it automatically adjust as per system timezone.

Apart from this DateTime structure contain one field called ‘Kind’. which contain current DateTime format kind and that is Utc , Local or Unspecified. Many of case when you store simple way DateTime and later you retrieve kind is unspecified. But when you store binary date and later you retrieve you get either Utc or Local.

Please give your comment or any new idea about storing datetime.

Friday, April 17, 2009

WebService Authenticate against proxy server.

When proxy server configured for PC or in a network , if it require authentication to make certain request then you have to use following code.

Error: (407) Proxy Authentication Required.

Here i am taking example of SharePoint List service. I added reference of SharePoint List Service.


ListSerivce lst = new ListSerivce();
//Get Default Proxy Setting
IWebProxy proxy = System.Net.WebRequest.DefaultWebProxy;
// Authenticate using network credential. In My case i need authentication using windows account.
proxy.Credential = new System.Net.NetworkCredential(“username”,”password”,”domain”);
lst.Proxy = proxy;
// Make Call to WebService Method.

You can even find System.Net.WebProxy.GetDefaultProxy() return default proxy setting but it is deprecated to better to use WebRequest.DefaultWebProxy.

You can even configure your own webproxy

Lists lst = new Lists();
System.Net.WebProxy proxy = new WebProxy();
proxy.Address = new Uri("
http://proxy:8090");
proxy.Credentials = new NetworkCredential ("username", "password", "domain");
lst.Proxy = proxy;

In both case credential pass as NetworkCredential but you can use CredentialCache to pass other type of credential.

Please give comment on this. Also if you have any better idea please free give your suggestion.

Thursday, March 5, 2009

Unauthorized (401.1) Exception calling Web Services in SharePoint (.Net Framework 3.5 )

After installing .NET Framework 3.5 sp1 following error may occur while making call to webservice. This thing mostly happen when you are trying to make webservice call using fully qualified domain name instead of IPAddress or Hostheader is used to map request on single port.

I found one strange thing in IIS Log that , for such request it is not sending authentication information to webservice request even though you pass it in NetworkCredential. One solution is to disable integrated authentication and use basic authentication. This will compromise with security but solve problem. Another solution that need to require registry changes. You can find it at following link with grate explanation.

http://www.crsw.com/mark/Lists/Posts/Post.aspx?ID=44
http://support.microsoft.com/default.aspx?scid=kb;EN-US;896861

SPAlert DynamicRecipient On Custom List

In SharePoint default. alert functionality available. You can subscribe Alert on List or ListItem using AlertMe action. But in certain situation you need to automize this alert. Like Alert automatically send to particular user even though he/she did not subscribe event.

There are two way to do . Create feature that receive ItemAdded or ItemUpdated Event , Find out user and email address , send email using SendEmail Functionality of SharePoint.

Another way is use DynamicRecipient property of SPAlert.

Sample List :

list

Here you can see that To Field is type of Person or Group. Send automatic email to user enter ‘To’ Field.

List Entry look Like (Edit View).

alert list entry

Note : UserName must have email id associated with him.SMTP also configured properly for site.

Now run following code against your site. (use console application).

SPSite site = new SPSite("http://yoursite");
SPWeb web = site.OpenWeb();
SPList lst = web.Lists["Alert Test"];
SPAlert alert = web.Alerts.Add();
alert.AlertFrequency = SPAlertFrequency.Immediate;
alert.AlertType = SPAlertType.List;
alert.EventType = SPEventType.All;
alert.DynamicRecipient = "To";
alert.List = lst;
alert.Status = SPAlertStatus.On;
alert.Title = “Auto Email Alert”;
alert.Filter = "<Query><IsNotNull><FieldRef Name='To'></FieldRef></IsNotNull></Query>";            
alert.Update();

You can even use FeatureReceiver to install/ Activate / deactivate this thing as a feature.

Saturday, January 24, 2009

Batch Update In SharePoint

SharePoint support batch update in List by webservice and SharePoint object model.

For Example i used sample Custom List (Orders).

image

1. By Use of Web Service.

SharePoint webservice allows update list items as a batch.At a time only one list can be updated by single webservice call.

CAML That use for Batch Update. Here i update item with ID 2 and create new item in Orders List in one webservice call.

<Batch OnError=’Continue’>
         <Method ID=’1’ Cmd=’Update’>
                <Field Name=’ID’ >2</Field>
                <Field Name=’OrderDate’ >2007-1-21</Field>
                <Field Name=’CustomerID’ >1;#Cust_1</Field>
         </Method>
         <Method ID=’2’ Cmd=’New’>
                <Field Name=’OrderDate’ >2007-1-21</Field>
                <Field Name=’CustomerID’ >2;#Cust_2</Field>
         </Method>
</Batch>

C# Code (Either Add web reference of SharePoint webservice or Create Proxy Class using wsdl.exe and use that class)

Lists lst = new Lists();
lst.Url = “http://<your site>/_vti_bin/lists.asmx”;
lst.Credentials = new System.Net.NetworkCredential ("test", "test");
XmlDocument doc = new XmlDocument();
XmlElement batchElement =  doc.CreateElement("Batch");
batchElement.SetAttribute("OnError", "Continue");
batchElement.InnerXml = "<Method ID='1' Cmd='Update'>" +
               "<Field Name='ID'>2</Field>" +
               "<Field Name='OrderDate'>2009-1-31</Field><Field Name='OrderDateTime'>2009-1-31</Field></Method><Method ID='2' Cmd='New'><Field Name='CustomerID'>1;#Cust_1</Field><Field Name='OrderDate'>2009-1-31</Field><Field Name='OrderDateTime'>2009-1-31</Field></Method>";
XmlNode result = lst.UpdateListItems("Orders", batchElement); // This line of code make webservice call to update lists.

One more thing In CAML displayed above has two bold line for CustomerID field. CustomerID is a LookUp Field. So i mention that date id;#Value (Commom lookup Structure).If you want to choose lookup value only by id then use following CAML for Field.

<Batch OnError=’Continue’>
         <Method ID=’1’ Cmd=’Update’>
                <Field Name=’ID’ >2</Field>
                <Field Name=’OrderDate’ >2007-1-21</Field>
                <Field Name=’CustomerID’  Type=’LookUp’ LookUpID=’True’>1</Field>
         </Method>
         <Method ID=’2’ Cmd=’New’>
                <Field Name=’OrderDate’ >2007-1-21</Field>
                <Field Name=’CustomerID’ Type=’LookUp’  LookUpID=’True’ >2</Field>
         </Method>
</Batch>

2. By Use Of SharePoint Object Model. (SPWeb.ProcessBatchData)

SharePoint Object Model has SPWeb class. SPWeb class has ProcessBatchData Method , this method is used to update Batch via object model. Even this method allows you update two list items in Single method call.

Sample CAML .
<?xml version="1.0" encoding="UTF-8"?>
<ows:Batch OnError="Continue">
  <Method ID="1">
    <SetList>71a9fac3-2e94-4246-8fec-41e30ea65b06</SetList>
    <SetVar Name="Cmd">Save</SetVar>
    <SetVar Name="ID">New</SetVar>
    <SetVar Name="urn:schemas-microsoft-com:office:office#OrderDate">2009-2-21</SetVar>
    <SetVar Name="urn:schemas-microsoft-com:office:office#OrderDateTime">2009-2-21</SetVar>
    <SetVar Name="urn:schemas-microsoft-com:office:office#CustomerID">1;#Cust_1</SetVar>
  </Method>
  <Method ID="2">
    <SetList>71a9fac3-2e94-4246-8fec-41e30ea65b06</SetList>
    <SetVar Name="Cmd">Save</SetVar>
    <SetVar Name="ID">3</SetVar>
    <SetVar Name="urn:schemas-microsoft-com:office:office#OrderDate">2009-2-21</SetVar>
    <SetVar Name="urn:schemas-microsoft-com:office:office#OrderDateTime">2009-2-21</SetVar>
    <SetVar Name="urn:schemas-microsoft-com:office:office#CustomerID">1;#Cust_1</SetVar>
  </Method>
 
<Method ID="3">
    <SetList>71a9fac3-2e94-4246-8fec-41e30ea65b06</SetList>
    <SetVar Name="Cmd">Delete</SetVar>
    <SetVar Name="ID">4</SetVar>
    <SetVar Name="urn:schemas-microsoft-com:office:office#OrderDate">2009-2-21</SetVar>
    <SetVar Name="urn:schemas-microsoft-com:office:office#OrderDateTime">2009-2-21</SetVar>
    <SetVar Name="urn:schemas-microsoft-com:office:office#CustomerID">2;#Cust_2</SetVar>
  </Method>
</ows:Batch>

In above SetList element set GUID of SPList. Here i only update Orders List but you can set another list id combine it with above by just adding another Method Element.

SetVar element with attribute Name ‘cmd’ used to identify type of functionality. It has mainly two values : Save and Delete . Save is used for either for New Item or in case of update existing item.

SetVar element with attribute Name ‘ID’ used to find out on which item it operate. ID value ‘New’ is for new item and in case of Update and Delete it should have valid id value. (Integer).

SetVar element with Name attribute value urn:schemas-microsoft-com:office:office#<Field_Name> indicate perticular field of ListItem,<Field_Name> should replace by respetive field internal name.

C# Code.

SPSite site = new SPSite("http://avani:45830");
SPWeb web = site.OpenWeb();
SPList lst = web.Lists["Orders"];
string batchFormat = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<ows:Batch OnError=\"Return\">{0}</ows:Batch>";

string methodFormat = "<Method ID=\"{0}\">" +
             "<SetList>{1}</SetList>" +
             "<SetVar Name=\"Cmd\">{2}</SetVar>" +
             "<SetVar Name=\"ID\">{3}</SetVar>" +
             "<SetVar Name=\"urn:schemas-microsoft-com:office:office#OrderDate\">{4}</SetVar>" +
             "<SetVar Name=\"urn:schemas-microsoft-com:office:office#OrderDateTime\">{5}</SetVar>" +
             "<SetVar Name=\"urn:schemas-microsoft-com:office:office#CustomerID\">{6}</SetVar>" +            
             "</Method>";

StringBuilder strmethodFormat = new StringBuilder();
strmethodFormat.AppendFormat(methodFormat, 1, lst.ID.ToString(), "Save", "New", "2009-2-21", "2009-2-21","1;#Cust_1");
strmethodFormat.AppendFormat(methodFormat, 2, lst.ID.ToString(), "Save", "3", "2009-2-21", "2009-2-21","1;#Cust_1");
strmethodFormat.AppendFormat(methodFormat, 3, lst.ID.ToString(), "Save", "4", "2009-2-21", "2009-2-21","2;#Cust_2");
string processtext = String.Format(batchFormat, strmethodFormat.ToString());

web.ProcessBatchData(processtext);

Other usefull post about Batch element creation through XLinq or Linq are
http://dotnetstep.blogspot.com/2009/01/xlinq-to-generate-batch-element-for.html
http://dotnetstep.blogspot.com/2009/01/sharepoint-to-linq.html

Sunday, January 18, 2009

XLinq To Generate Batch Element For SharePoint ListService

In my article (http://dotnetstep.blogspot.com/2009/01/update-datetime-column-using-webservice.html) i used SharePoint List Service to update SharePoint ListItems. In that article i manually set batchElement.InnerXml property with Xml.

When there is to many row and you want to generate it automatically then you can use XLinq.

In following example first select all items from orders List then use item id and update each item orderdate and orderdatetime column with current date and current datetime respectively.

Lists lst = new Lists();
lst.Url = “http://<your site>/_vti_bin/lists.asmx”;
lst.Credentials = new System.Net.NetworkCredential("test", "test"); // Site Administrator username and password
XmlNode resultNode = lst.GetListItems("Orders", String.Empty, null, null, int.MaxValue.ToString(), null, String.Empty);

// Use XElement To Generate Batch Element Automatically

XElement orders = XElement.Parse(resultNode.OuterXml);
XName name = XName.Get("data","urn:schemas-microsoft-com:rowset");
int methodsequence=1;
XElement updatexml =
new XElement("Batch", new XAttribute("OnError","Continue"),
from order in orders.Element(name).Elements()
// you can also use where condition over here
// for eg. where order.Attribure(“ows_ID”).value = “2”

select new  XElement("Method", 
new XAttribute("ID", (methodsequence++).ToString()), 
new XAttribute("Cmd", "Update"),
new XElement("Field", new XAttribute("Name", "ID"), order.Attribute("ows_ID").Value),
new XElement("Field",new XAttribute("Name","OrderDate"),DateTime.Now.SharepointFormatDate()),
new XElement("Field", new XAttribute("Name", "OrderDateTime"), DateTime.Now.SharepointFormatDateTime())));


Now Convert XElement to XmlNode as UpdateListItems only accept XmlNode as parameter.

XmlDocument doc=  new XmlDocument();
doc.LoadXml(updatexml.ToString());
lst.UpdateListItems("Orders",doc.FirstChild);

Update DateTime Column Using SharePoint ListService

SharePoint webservice can be used to update item or items in SharePoint List.When SharePoint List contains “Date And Time” Column with only Date or Date And Time Mode, you have to pass date or datetime in specific format so it can be update by webservice.

UpdateListItems method is used for this purpose.

To format DateTime for SharePoint Webservice, i created following extension methods.

// Extensions Method

public static class DateTimeExtensions
{
    // Only Date Column
    public static string SharepointFormatDate(this DateTime dt)
    {
        return dt.ToString("yyyy-MM-dd");
    }

    // Date And Time column
    public static string SharepointFormatDateTime(this DateTime dt)
    {
        return dt.ToString("yyyy-MM-ddTHH:mm:ssZ");
    }
}

To Update List using webservice.

System.Xml.XmlDocument doc = new System.Xml.XmlDocument();           
System.Xml.XmlElement batchElement = doc.CreateElement("Batch");
batchElement.SetAttribute("OnError", "Continue");
batchElement.SetAttribute("ListVersion", "1");
batchElement.InnerXml =”<Method ID='1' Cmd='Update'>" + "<Field Name='ID'>2</Field>" +
"<Field Name='OrderDate'>”+ DateTime.Now.SharepointFormatDate() +”</Field><Field Name='OrderDateTime'>”+ DateTime.Now.SharepointFormatDateTime()  +”</Field></Method>";

// List Serivce object  (Add web reference for this)
Lists lst = new Lists();
lst.Url = “http://<your site>/_vti_bin/lists.asmx” ;
lst.Credentials = new System.Net.NetworkCredential("test", "test");
lst.UpdateListItems(“Orders”,batchElement);

In above code <Field Name=’ID’>2</Field> is used to identify unique row that need to be update. In Sample only item with id 2 is updated. In order to update multiple items just add another method element. For example, (This update both item with id 2 and 3)

batchElement.InnetXml =

“<Method ID='1' Cmd='Update'>" + "<Field Name='ID'>2</Field>" +
"<Field Name='OrderDate'>”+ DateTime.Now.SharepointFormatDate() +”</Field><Field Name='OrderDateTime'>”+ DateTime.Now.SharepointFormatDateTime()  +”</Field></Method>" +
"<Method ID='2' Cmd='Update'>" + "<Field Name='ID'>3</Field>" +
"<Field Name='OrderDate'>”+ DateTime.Now.SharepointFormatDate() +”</Field><Field Name='OrderDateTime'>”+ DateTime.Now.SharepointFormatDateTime()  +”</Field></Method>"

Same way you can update another type of columns too.

More information available at following location.

http://msdn.microsoft.com/en-us/library/lists.lists.updatelistitems.aspx
http://msdn.microsoft.com/en-us/library/ms440289.aspx

Sunday, January 11, 2009

SharePoint to Linq

Here specially talking about SharePoint and XLinq. When you choose SharePoint webservice to get data from SharePoint List, data return by web service is in XML format. To read this data as well as filter data XLinq is more powerful.

How to Use SharePoint webservice.
1. Add Web reference or generate proxy using WSDL tool.
then

Lists lst = new Lists();
lst.Url = “http://<your site>/_vti_bin/lists.asmx”;
lst.Credentials = new System.Net.NetworkCredential("test", "test");

Now use GetListItems to retrieve all items from SharePoint List. I would suggest take scenario into consideration. If you require less data to be return from SharePoint List then use Query in GetListItems function. ( Here concentration is on XLinq so it is out of scope for this post).

XmlNode resultNode = lst.GetListItems("Customers", String.Empty, null, null, int.MaxValue.ToString(), null, String.Empty);

XElement (System.Xml.Linq) to read result into XElement
XElement customers = XElement.Parse(resultNode.OuterXml);

XName to read type of Node.
XName name = XName.Get("data","urn:schemas-microsoft-com:rowset");

Read All Node Using Linq
var filtercustomers = from ele in customers.Element(name).Elements()                                
select new {CustomerID =  ele.Attribute("ows_ID").Value , Name = ele.Attribute("ows_CustomerName").Value , City = ele.Attribute("ows_CustomerCity").Value , Country = ele.Attribute("ows_CustomerCountry").Value};

Filtering Node using XLinq
var filtercustomers = from ele in customers.Element(name).Elements()   
where ele.Attribute("ows_CustomerCountry").Value == "India" && ele.Attribute("ows_CustomerCity").Value == "Banglore"                             
select new {CustomerID =  ele.Attribute("ows_ID").Value , Name = ele.Attribute("ows_CustomerName").Value , City = ele.Attribute("ows_CustomerCity").Value , Country = ele.Attribute("ows_CustomerCountry").Value};

Join Using XLinq

1. Join Two Result
This is use full case when join in needed on filter data set.
In following code customers and orders represent two sample reslut set.

XmlNode resultNode = lst.GetListItems("Customers", String.Empty, null, null, int.MaxValue.ToString(), null, String.Empty);
            XElement customers = XElement.Parse(resultNode.OuterXml);
            XName name = XName.Get("data","urn:schemas-microsoft-com:rowset");

            var filtercustomers = from ele in customers.Element(name).Elements()         
where ele.Attribute("ows_CustomerCountry").Value == "India" && ele.Attribute("ows_CustomerCity").Value == "Banglore"                       
select new {CustomerID =  ele.Attribute("ows_ID").Value , Name = ele.Attribute("ows_CustomerName").Value , City = ele.Attribute("ows_CustomerCity").Value , Country = ele.Attribute("ows_CustomerCountry").Value};

            // Retrive data From Orders
            resultNode = lst.GetListItems("Orders", String.Empty, null, null, int.MaxValue.ToString(), null, String.Empty);
            XElement orders = XElement.Parse(resultNode.OuterXml);
            var filterorders = from ele in orders.Element(name).Elements()                                 
                                  select new { OrderID = ele.Attribute("ows_ID").Value, CustomerID = ele.Attribute("ows_CustomerID").Value.Split(new string[]{";#"},StringSplitOptions.None)[0] , OrderDate = ele.Attribute("ows_OrderDate").Value };

Join Results

var joinresult = from customerele in filtercustomers
                     join orderele in filterorders on customerele.CustomerID equals orderele.CustomerID
                     select new { customerele, orderele };

2. Directly Join Two XElement

var directjoin = from customerele in customers.Element(name).Elements()
                             join orderele in orders.Elements(name).Elements() on customerele.Attribute("ows_ID").Value equals orderele.Attribute("ows_CustomerID").Value.Split(new string[] { ";#" }, StringSplitOptions.None)[0]
                             select new { CustomerID = customerele.Attribute("ows_ID").Value, Name = customerele.Attribute("ows_CustomerName").Value, City = customerele.Attribute("ows_CustomerCity").Value, Country = customerele.Attribute("ows_CustomerCountry").Value, OrderID = orderele.Attribute("ows_ID").Value, OrderDate = orderele.Attribute("ows_OrderDate").Value };

Note: When working with webservice do care while retrieve data. Whatever data needed from single list for operation try to retrieve in single webservice call instead of making many web service call.For my point of view this will improve the performance.

Sunday, January 4, 2009

Custom GridView Field For SharePoint LookUp Column

In Sharepoint When retrieve data using web service, there is need for customization during display in GridView. There are two ways to do this.

1. First Way

Use Template Column of GridView. Write Inline coding to Format data.

For Example .

In Codebehind file Write Following Function.

To Fetch data using web service.

public DataTable GetData()
{     

DataTable dt = new DataTable();
Lists lst = new Lists();
lst.Url = "
/_vti_bin/lists.asmx";'>http://<your site>/_vti_bin/lists.asmx";
lst.Credentials = new System.Net.NetworkCredential("test", "test"); 
XmlNode result =lst.GetListItems("Orders", String.Empty, null, null, int.MaxValue.ToString(), null, string.Empty); 
System.IO.StringReader read = new System.IO.StringReader(result.OuterXml); 
DataSet dst = new DataSet(); 
dst.ReadXml(read); 
if (dst.Tables.Count == 2 && Convert.ToInt32(dst.Tables[0].Rows[0]["ItemCount"].ToString()) > 0)
        {
            dt = dst.Tables[1];
        }
        else
        {
            dt.Columns.Add(new DataColumn("ows_CustomerID",typeof(string)));
        }
        return dt;

    }

// Enum For Display Mode of LookUpField.

public enum Mode
{
        ID,
        Value,
        All
};

// Function that format data (This Fuction must be Public or Proctected)

protected string GetLookupValue(string value,Mode LookUpDisplayMode)
    {
        string returnVal = String.Empty;
        string[] str;
        try
        {
            switch (LookUpDisplayMode)
            {
                case Mode.All:
                    returnVal = value;
                    break;
                case Mode.ID:
                    str = value.Split(new string[] { ";#" }, StringSplitOptions.None);
                    returnVal = str[0];
                    break;
                case Mode.Value:
                    str = value.Split(new string[] { ";#" }, StringSplitOptions.None);
                    returnVal = str[1];
                    break;
            }
        }
        catch
        {
        }
        return returnVal;
    }

And in ASPX Page.

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" >
        <Columns>                     
            <asp:TemplateField>
                <ItemTemplate>
                    <%# GetLookupValue(Eval("ows_CustomerID").ToString(),Mode.ID) %>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField>
                <ItemTemplate>
                    <%# GetLookupValue(Eval("ows_CustomerID").ToString(),Mode.Value) %>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField>
                <ItemTemplate>
                    <%# GetLookupValue(Eval("ows_CustomerID").ToString(),Mode.All) %>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
</asp:GridView>
   

2. Other Way

This way is create custom DataBoundField that inherits from BoundField.This is required one time coding as well as avoid inline coding.

Put following class in either App_Code or create class library and use it any application you want.

//LookupField Class

public class LookupField : BoundField
    {
        public enum Mode { ID, Value, All};

        public LookupField()
        {
}

        public Mode LookUpDisplayMode
        {
            get;
            set;
        }

        protected override string FormatDataValue(object dataValue, bool encode)
        {
            dataValue = GetLookupValue(dataValue.ToString());
            return base.FormatDataValue(dataValue, encode);
        }

        protected override void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)
        {
            if(rowState == DataControlRowState.Normal || rowState == DataControlRowState.Selected || rowState == DataControlRowState.Alternate)
                base.InitializeDataCell(cell, rowState);           
            else
            {                              
                TextBox txt = new TextBox();               
                cell.Controls.Add(txt);
                txt.DataBinding += new EventHandler(OnDataBindField);               
            }           
        }

        protected override DataControlField CreateField()
        {
            return new LookupField();
        }

        protected override void OnDataBindField(object sender, EventArgs e)
        {
            Control c = sender as Control;
            if(c is TableCell)
                base.OnDataBindField(sender, e);
            else if (c is TextBox)
            {
                string val=  GetLookupValue(this.GetValue(c.NamingContainer).ToString());
                ((TextBox)c).Text = val;
            }
        }
        private string GetLookupValue(string value)
        {
            string returnVal = String.Empty;
            string[] str;
            try
            {
                switch (LookUpDisplayMode)
                {
                    case Mode.All:
                        returnVal = value;
                        break;
                    case Mode.ID:
                        str = value.Split(new string[] { ";#" }, StringSplitOptions.None);
                        returnVal = str[0];
                        break;
                    case Mode.Value:
                        str = value.Split(new string[] { ";#" }, StringSplitOptions.None);
                        returnVal = str[1];
                        break;
                }
            }
            catch
            {
            }
            return returnVal;
        }
    }

// ASPX Page.
Register Control
<%@ Register TagPrefix="CC" Assembly="App_Code" Namespace="LookupFields" %>

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false"
            AutoGenerateEditButton="true" onrowediting="GridView1_RowEditing">
        <Columns>
            <CC:LookupField DataField="ows_CustomerID" LookUpDisplayMode="ID" HeaderText="CustomerID"></CC:LookupField>
            <CC:LookupField DataField="ows_CustomerID" LookUpDisplayMode="Value" HeaderText="CustomerValue"></CC:LookupField>
            <CC:LookupField DataField="ows_CustomerID" LookUpDisplayMode="All" HeaderText="Customer"></CC:LookupField>

</asp:GridView>

In above two way use following code to bind GridView.

//ASPX Page

protected void Page_Load(object sender, EventArgs e)
   {
       if (!Page.IsPostBack)
       {
           GridView1.DataSource = GetData();
           GridView1.DataBind();
       }
   }

Note: Implementation of custom LookupField is not complete. You may required to add or override few more function in order to work with diffrent mode of GridView Row. (Row Selection , Editing etc).

Please give me your comment.

Tuesday, December 30, 2008

Linq to SharePoint List. (Where , Join )

This article give you information regarding how to use Liinq with SharePoint List to fetch data from SPList.

For Example there are three SharePoint List . Customers , Orders , OrderDetails. (Please See image below). In Orders list CustomerID is lookup field and in OrderDetails list OrderID is lookup field.

Customer

orders

Order Details

Now Get All Customer From Customer List using Linq.

SPSite site = new SPSite("http://localhost:45833"); 
SPWeb web = site.OpenWeb();
SPList lstCustomer = web.Lists["Customers"];

var customers = from SPListItem customer in lstCustomer.Items
                       select customer;

by use of SPListItem (As we use select customer in Linq query)
foreach (SPListItem item in customers)
{
Console.WriteLine(item.ID.ToString() + "-" +item["CustomerName"].ToString());
}

or by using ananymous type

var customers = from SPListItem customer in lstCustomer.Items
                       select new {ID = customer.ID.ToString(), Name= customer[“CustomerName”].ToString()};
foreach (var item in customers)
{
Console.WriteLine(item.ID + "-" + item.Name);
}

use of where clause with this

var customers = from SPListItem customer in lstCustomer.Items
                       where customer.ID == 1
                       select new { ID = customer.ID.ToString(), Name = customer["CustomerName"].ToString() };

Join Three List to get Related Data

SPList lstCustomer = web.Lists["Customers"];
SPList lstorders = web.Lists["Orders"];
SPList lstorderdetails = web.Lists["OrderDetails"];
var customerorders =

from SPListItem customer in lstCustomer.Items
join SPListItem order in lstorders.Items on customer.ID.ToString() equals order["CustomerID"].ToString().Split(new string[]{";#"},StringSplitOptions.None)[0]
join SPListItem orderdetail in lstorderdetails.Items on order.ID.ToString() equals orderdetail["OrderID"].ToString().Split(new string[] { ";#" }, StringSplitOptions.None)[0]                                
select new {Product = orderdetail["Product"].ToString() , Price = Convert.ToDouble(orderdetail["Price"].ToString()) , Qty = Convert.ToInt32(orderdetail["Qty"].ToString()) , OrderID = order.ID , OrderDate = order["OrderDate"].ToString() , CustomerID = customer.ID.ToString(), CustomerName = customer["CustomerName"].ToString() };


foreach (var item in customerorders)
               {
                   Console.WriteLine(item.Product + "  " + item.Price.ToString() + "," + item.Qty.ToString() + ","+ (item.Price * item.Qty).ToString() + ","+ item.OrderID.ToString() + "," + item.OrderDate + "," + item.CustomerName);
               }

                  Note :In above code, I used split operation on string in order to compare LookUp Field ID Value with ID of parent List. There is also posibility to join more than three tables.

For that you have to use nested this join inside other. Please give your comment or advice on this.

Tuesday, October 7, 2008

The File Exists. (Exception from HRESULT: 0x80070050)

This error i got when i removed Active Directory from PC. Actually first i install active directory. Then on next day iremoved it from PC. So it remove all account from my PC. Only administrator are present over there. So none of other program working. Even IIS stop working. I removed iis and then reinstall it . Then configure .net by using aspnet_regiis command. This will create ASPNET user account. Also Reinstallation of IIS create IUSR_ <Machine Name> account.After everything runs ok sharepoint stop working . I removed sharepoint and reinstall it. In Installation of sharepoint i choose same database as previous installation.So it create all sites in IIS. After successfull installtion Central Admin so me error message The File Exists. (Exception from HRESULT: 0x80070050). So for solution i create one user in system with adiminstrators as group and try to login using that user. ( I am not able to login using administrator account).

After this i choose each of application and add new user as a secondary account.

Central Administration > Application Management > Site Collection Owners

Change each of site collection secondary user. This solution works for me.May be cause is different in certain condition.(Possible then restart PC after user setting in all site collection).Cause of problem is related to SID.

Sunday, October 5, 2008

Retrieve SharePoint List With Folders and Files ( Tree Structure)

To retrieve SPList structure wise use SPQuery to retrieve childitems.

There is property called FileSystemObjectType of SPListItem that identifies the current item (Either Folder or File).

SPSite site = new SPSite("http://localhost:43588");
SPWeb web = site.OpenWeb();
SPList list = web.Lists["WebLink List"];
Response.Write("<span style='padding-left:0px'>" + list.RootFolder.Name + "</span>" + "</br>");
GetChildItems(list, list.RootFolder,10);

GetChildItems is a recrusive function.

GetChildItems Function

private void GetChildItems(SPList lst , SPFolder folder,int padding)
   {
       SPQuery query = new SPQuery();
       query.Folder = folder;
       SPListItemCollection col =  lst.GetItems(query);
       foreach (SPListItem item in col)
       {
           if (item.FileSystemObjectType == SPFileSystemObjectType.File)
           {
               Response.Write("<span style='padding-left:"+ padding +"px'>"+item["URL"]+"</span>"+ "</br>");
           }
           else if (item.FileSystemObjectType == SPFileSystemObjectType.Folder)
           {               
               Response.Write("<span style='padding-left:" + padding + "px'>" + item.Title + "</span>" + "</br>");
               GetChildItems(lst, item.Folder,padding+30);
           }
       }
   }