Tuesday, December 30, 2008

Windows Identity Impersonation

Sometime in window application it is required that it run in context of user account other than current login account.Few condition that required this is

1) Window Application that authenticate and authorize user by his/her user account.

2) SharePoint sometime required this to gain access of resource that is not granted for SharePoint users.

You can use following code to impersonate particular user.

[System.Runtime.InteropServices.DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(
String lpszUsername,
String lpszDomain,
        String lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        ref IntPtr phToken);
        [System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);

        static void Main(string[] args)
        {

            IntPtr usertoken = new IntPtr(0);
            bool b = LogonUser("test", "local", "123", 2, 0, ref usertoken);
            if (b == true)
            {
                System.Security.Principal.WindowsIdentity iden = new System.Security.Principal.WindowsIdentity(usertoken);
                System.Security.Principal.WindowsImpersonationContext con = iden.Impersonate();

// You Code that required impersonation

con.undo()

}

}

Note : Impersonation can be used in any type of application. (Window Application , Web Application , Class Library).

In Web Application web.config contains specific <identity> attribute for impersonation.

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.

Wednesday, December 17, 2008

MCTS 70-528 Book update (MCTS Self-Paced Training Kit (Exam 70-528))

MCTS book update. If you have book called MCTS Self-Paced Training Kit (Exam 70-528): Microsoft .NET Framework 2.0 Web-Based Client Development, then you have to look at following correction.

 

http://support.microsoft.com/kb/930739

Monday, December 15, 2008

MCTS Self-Paced Training Kit Exam 70-536 Correction and Updates link.

MCTS 70-536 Self-Paced Training kit contains some wrong information. Microsoft support site provides updates in book and materials associated with book. (Like CD, Practice Test)

Part 1 : http://support.microsoft.com/kb/923018

Part 2 : http://support.microsoft.com/kb/935218

Part 3 : http://support.microsoft.com/kb/949730/

Part 4 : http://support.microsoft.com/kb/949734/

Friday, December 5, 2008

New controls for .NET Framework 3.5 SP1

This is really a nice thing that Microsoft did in .NET Framework 3.5 SP1, Introduce really cool Chart Controls. This chart controls is for Windows as well as Web Application.

You can download it from Microsoft Site.

Link : Download Chart Control

In related download you can find document and VS 2008 Add-on for this control.

Thursday, October 9, 2008

Change The Location Of GAC

By default whne .NET framework install then it will install global assembly cache to operating system root drive:\windows\assembly.

In order to change its location you need to update following registry.

Go to  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fusion

Add CacheLocation (REG_SZ) key and set it to new location.

Suppose your new location is c:\bkfrm then CacheLocation c:\bkfrm. Now .NET framework search for assembly directory inside c:\bkfrm.

Use code to backup assembly and give source directory c:\windows\assembly and destination (f you take c:\bkfrm) then c:\bkfrm\assembly. (assembly folder must required in any of case).

Note: It is required to change in registry so it may cause problem.

Global Assembly Cache Directory Structure and Backup

Whenever .NET framework install on PC. There is one specific directory created called Global Assembly Cache.It contains all assemblies that available to all application on machine.

To open global assembly cache go to run and type assembly or if your sysroot in C drive then go for c:\windows\assembly.

assembly

It is a special directory so it look like this. By default it store data in directory structure.Please look at following image.

assemblyst

To Copy global assembly cache you can use following code in C# 2.0.

static void Main(string[] args)
        {
            string assemblyfolderpath = "d:\\windows\\assembly";
            string copypath = "c:\\newtest123";
            Directory.CreateDirectory(copypath);
            DirectoryInfo dir = new DirectoryInfo(assemblyfolderpath);
            ReadDir(dir,copypath);           
            Console.ReadLine();
        }

        static void ReadDir(DirectoryInfo dir,string copypath)
        {
            if (dir != null)
            {
              FileInfo[] infos =  dir.GetFiles();
              for (int i = 0; i < infos.Length; i++)
              {
                  Console.WriteLine(infos[i].Name);
                  infos[i].CopyTo(copypath + "/" + infos[i].Name);
              }
              DirectoryInfo[] dirs = dir.GetDirectories();
              for (int i = 0; i < dirs.Length; i++)
              {
                  Console.WriteLine(dirs[i].Name);
                  Directory.CreateDirectory(copypath + "/" + dirs[i].Name);
                  ReadDir(dirs[i],copypath +"/"+ dirs[i].Name);
              }
            }
        }

This is the way by which you can create copy of Assembly.

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);
           }
       }
   }

Saturday, October 4, 2008

Event Null Checking In VB.NET Before It Raise

For Example In C#

class MyClass
    {
        public delegate void MyEventHandler(int i);
        public event MyEventHandler MyEvent;

        public MyClass()
        {
        }

        public void FireEvent()
        {
            if (MyEvent != null)
            {
                MyEvent(10);
            }
        }
    }

In above example we check  MyEvent has reference or not by checking if(MyEvent != null) in FireEvent Method. So Event only raise when it has reference.

In VB.NET raiseevent internally check this thing. but if you want to manually check then use following method.

VB.NET Example:

Public Class MyClass1
    Public Event MyEvent(ByVal i As Integer)
    Public Sub New()
    End Sub
    Public Sub FireEvent()
        If MyEventEvent IsNot Nothing Then
            RaiseEvent MyEvent(10)
        End If
    End Sub
End Class

In VB.net that is not necessary to create delegate. You can directly create event. If you want to check that event has reference or not if you have to Add “Event” extra word at the end of Event Name . In above example out event is MyEvent so we did check MyEventEvent is nothing or not. We can not directly check MyEvent is not nothing in VB.NET.

One more thing to know VB.net allow us to create event directly ( Without creating delegate). But implicitly it create delegate that has same name like MyEventEvent. Suppose you declare event Add then AddEvent delegate automatically created. (Please see below image).

vbnetevent

Sunday, September 14, 2008

Passing reference type ByVal or ByRef.

In .net framework there is two type set. One is reference type and another one is value type.

This post is about passing reference type by val or byref.

1. Passing ByVal.

Example:
class A
{
int i;
}


class bMain
{
public static void main()
{
A var = new A();
var.i = 10;
Console.WriteLine("Before Pass{0}",var.i);
TestFun(var);
Console.WriteLine("After Pass{0}",var.i);
}
public static void TestFun(A a)
{
a.i = 20;
}
}

output:
Before Passs : 10
After Pass: 20

Here you can see default behavior of reference type. When reference type pass by value then you can change member of that variable. But what happen when you try to reassign variable it self.

Please following code For TestFun

public static void TestFun(A a)
{
a = new A();
a.i = 20;
Console.WriteLine("Inside Fun: {0}",a.i);
}

Output:
Before Pass : 10
Inside Fun: 20
After Pass: 10

Because when reference type pass by value not actual reference is passed. Instead of that copy of reference is passed. When you try to update that parameter inself it will not take affect outside scope of function.

2. Passing By Ref.

class A
{
int i;
}


class bMain
{
public static void main()
{
A var = new A();
var.i = 10;
Console.WriteLine("Before Pass{0}",var.i);
TestFun(var);
Console.WriteLine("After Pass{0}",var.i);
}
public static void TestFun(ref A a)
{
a.i = 20;
}
}

output:
Before Pass : 10
After Pass :20

Now we update reference itself.
public static void TestFun(ref A a)
{
a = new A();
a.i = 20;
Console.WriteLine("Inside Fun {0}",a.i);
}
Output:
Before Pass: 10
Inside Fun: 20
After Pass: 20

Here actual reference is passed. So it will take affect outside function too.

You can get more detail at following location:
http://msdn.microsoft.com/en-us/library/0f66670z(vs.71).aspx#vclrfpassingmethodparameters_referencetypes

Tuesday, September 9, 2008

Bind Generic List To DataBound Control.

Suppose you have class called Person that represent person.
(This is specific to ASP.net 3.5 , C# 3.0)

public class Person
{
public Person()
{
this.Name = "";
this.Email = "";
}

public string Name
{
get;
set;
}
public string Email
{
get;
set;
}
}

Generic feature available in .NET Framework 2.0 onwards. So you can use that to create generic list.

Here we create List of Person using following code.

System.Collections.Generic.List lst =
new System.Collections.Generic.List()
{
new Person{Name = "XYZ" , Email = "xyz@xyz.com"},
new Person{Name = "123" , Email = "123@xyz.com"}
};

Bind to GridView.

GridView1.DataSource = lst;
GridView.DataBind();


Bind To ListBox

Listbox1.DataSource = lst;
Listbox1.DataBind();

Binding with gridview works perfect and display Name and Email as column. Same is not happen with ListBox.

ListBox Display item something like

Person
Person But it not display anything.

For that you have to do following thing.

ListBox1.DataSource =lst;
ListBox1.DataTextField = "Name";
ListBox1.DataValueField = "Email";
ListBox1.DataBind();

So It display name and ListBox1.SelectedValue contain appropiate Eamil Id.

Monday, September 8, 2008

Prevent site from IFRAME

Sometime it is neccessary to prevent site or perticular page opening in IFRAME. To do that use following code in page or site. (Someway every page on site).

<script language="javascript">
if(top != self)
top.location = self.location;
</script>

If some page written above code and still you want to open that page in IFRAME. You need to use following syntax. This is only supported in IE.

<iframe src="write your url that contain above code." width="500" Height="500" security="restricted">

If any one have firefox solution for this please inform me.

Friday, August 15, 2008

JSonSerialization Error Solution

Sometime when working with ScriptSevice and ScriptMethod in ASP.net webservice following error may occur.

Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.

Reason for this is JavaScript Serialization setting . This allow maximum 2097152 character by default. It method return string larger then this then it throw above error.

Solution for this is to put following configuration in web.config file.

<connectionStrings>
</connectionStrings>
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="500000"></jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>




In above configuration instead you can set maxJsonLength to certain value so it allow larger string.

Maximum value for that field is 2147483647 as this property is System.Int32.

More information you can find it on following location.
http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.maxjsonlength.aspx

Wednesday, August 13, 2008

bool vs bitvector32 in C#

In application sometime you need more boolean fields.Also that memory usage and performance is main concern.

For example you require 50 boolean fields. If you create 50 boolean variable
like
bool b1,b2,b3....b50;
or
create array of 50 than bool[] b = new bool[50]; then also each bool veriable require 1 byte. so total space usage 50 * 1 = 50bytes.

If you use bitvector32 instead of creating array or 50 variable then it just require 4byte. Each bitvector32 can hold upto 32 different flags.

so for 50 we just need two bitvector32,and space usage reduce to 8 byte instead of 50 byte.


BitArray is also provide functionality like bitvector32 but it is class so it overhead with instance of class, but bitvector32 is simple structure so it reduce that over head too.

Example:

BitVector32 bv = new BitVector32(0); This will assign all bits to 0, as 0 binary representation is 00000000000000000000000000000000.

BitVector32 bv = new BitVector32(-1); This will assign all bits set to 1. As –1 binary representation is 11111111111111111111111111111111. (Two’s complement).

You can choose BitArray over BitVector32 when size of array like 40 , 48. That is not in multiple of 32. ( This is just a suggestion).

More information you can find at following location.
http://msdn.microsoft.com/en-us/library/system.collections.specialized.bitvector32.aspx
http://msdn.microsoft.com/en-us/library/eahchzkf.aspx(C# ref)

Tuesday, August 12, 2008

Find distinct value from DataSet/DataTable in .NET

Suppose you have dataset that contain data in following manner

ID Name Country
----------------------------
1 X USA
2 Y INDIA
3 Z INDIA
This is a DataTable name EmpInfo.

Now you want to select distinct country value from above table.

DataTable country = EmpInfo.DefaultView.ToTable(true,"Country");

Now country datatable contain distinct country value from EmpInfo Table.

You get more information from following link.
http://msdn.microsoft.com/en-us/library/wec2b2e6.aspx

Tuesday, July 1, 2008

Custom SessionID In ASP.net 2.0

By default asp.net 2.0 create sessionid like this kidt1m55iyqcx2vrtkn3z0ba. But requirement is such that you need to use your own algorithm to generate sessionid. For this pupose you have to create class that inherit from SessionIDManager class and override it CreateSessionID and Validate methods.
For Example : I want to use GUID as sessionid .
public class CustomSessionID : System.Web.SessionState.SessionIDManager
{
public override string CreateSessionID(HttpContext context)
{
return Guid.NewGuid().ToString();
}
public override bool Validate(string id)
{
try
{
Guid idtest = new Guid(id);
if (idtest.ToString() == id)
return true;
}
catch
{
return false;
}
return false;
}
}

You can also use DateTime.Now().Ticks as SessionID, or any custom string as a sessionid.

This is very useful case when you want to functionality like same sessionid generate for sameuser.

You also have to set web.config sessionStat Section in following manner. Here i assume that above class present in App_code directory . but you can create class library and refrence that class in sessionState session.

web.config setting.

<sessionState sessionIDManagerType="CustomSessionID,App_code" >
</sessionState>