Today I will tell you how to use resource file in sharepoint.
Resource file is stored in location '12/Resources' directory.
If you don't know where this '12' folder exists , then the full path is:
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12
There you will see a folder named 'Rescources'.
Suppose we have a resource file named CustomResource.resx with a key/value pair as :
userName : TestUser
Now, if we need to access the value of key userName from resource file from our application, we need to do:
string srcName = SPUtility.GetLocalizedString(
"$Resources:CustomResource,userName", "CustomResource", 1033);
You can also use the above code like this also:
string srcName = SPUtility.GetLocalizedString(
"$Resources:userName", "CustomResource", 1033);
Varun Sharma
This blog is dedicated to new technologies of Microsoft, including LINQ, sharepoint, ADO.NET entity framework and lot more
add
Monday, March 23, 2009
Wednesday, March 18, 2009
Sometimes, I set breakpoints and attach to the process but Visual Studio skips loading the symbols if I’m debugging a deployed assembly to the GAC and
Easy, Open Tools -> Options -> Debugging.
You’ll find an option labeled Enable Just My Code (Managed Only) as shown in the figure which is checked by default. Uncheck this option to be able to debug the assemblies located in the GAC. There is a common myth among .NET developers in general and especially SharePoint ones, that in order to debug assemblies that have been deployed to the GAC, you need to copy the debug symbols (PDB File) to the GAC as well. This was true in the early days of .NET but this is no longer true.
You’ll find an option labeled Enable Just My Code (Managed Only) as shown in the figure which is checked by default. Uncheck this option to be able to debug the assemblies located in the GAC. There is a common myth among .NET developers in general and especially SharePoint ones, that in order to debug assemblies that have been deployed to the GAC, you need to copy the debug symbols (PDB File) to the GAC as well. This was true in the early days of .NET but this is no longer true.
When I try to attach the debugger to the W3WP.exe process to debug, I always see multiple instances of it. Which one should I attach to?
Ok, this is easy too. Just follow the following steps.
Open the command prompt window, run IISAPP to get a list of the current instances of W3WP.exe.
Note the PID of the instance that corresponds to your web application.
Now return to VS, select Debug -> Attach to process and attach to the W3wp.exe instance with an ID equivalent to the PID you got in step 2 -> click Attach.
Now you can trace through the code and find the error causes easily.
But the question still remains, why sometimes are they more than one w3wp.exe instance? This is because the SharePoint Administration Site Collection and the SSP Administration site always have their own Application pools for error isolation purposes.
Open the command prompt window, run IISAPP to get a list of the current instances of W3WP.exe.
Note the PID of the instance that corresponds to your web application.
Now return to VS, select Debug -> Attach to process and attach to the W3wp.exe instance with an ID equivalent to the PID you got in step 2 -> click Attach.
Now you can trace through the code and find the error causes easily.
But the question still remains, why sometimes are they more than one w3wp.exe instance? This is because the SharePoint Administration Site Collection and the SSP Administration site always have their own Application pools for error isolation purposes.
How to get detailed error message in Sharepoint site
SharePoint uses a user friendly (Yellow & Blue) error page to show that a problem occurred. Yeah, they call it the user friendly page, but we, as developers, call it the Annoying Page. The first time I wrote SharePoint code, I received a screen like the one shown in the figure below:
This error page points out that an assembly has thrown an unhandled System.Exception. Sometimes, the user-friendly error page will specify the nature of the error if the code that threw the exception used something more specific than System.Exception or if it included a message in the Exception class constructor.
We need to get a more detailed Error Message than the annoying “Unexpected error has occurred “. This can be achieved by doing three modifications to the Web.Config file from the virtual directory containing your SharePoint application. These modifications are listed in the next table.
Tag
customErrors Mode :Off or Remote only
SafeMode CallStack : True
SafeMode AllowPageLevelTrace: True
No Custom Errors shows the full error to every client, every time. This is typically used Development environment, since there are no clients using it.
I recommend using the Debug Config feature to automate this process. This is just a feature that when you activate on a web application, it automatically tweaks the Web.Config of the specified web application across the farm.
This error page points out that an assembly has thrown an unhandled System.Exception. Sometimes, the user-friendly error page will specify the nature of the error if the code that threw the exception used something more specific than System.Exception or if it included a message in the Exception class constructor.
We need to get a more detailed Error Message than the annoying “Unexpected error has occurred “. This can be achieved by doing three modifications to the Web.Config file from the virtual directory containing your SharePoint application. These modifications are listed in the next table.
Tag
customErrors Mode :Off or Remote only
SafeMode CallStack : True
SafeMode AllowPageLevelTrace: True
No Custom Errors shows the full error to every client, every time. This is typically used Development environment, since there are no clients using it.
I recommend using the Debug Config feature to automate this process. This is just a feature that when you activate on a web application, it automatically tweaks the Web.Config of the specified web application across the farm.
Tuesday, March 17, 2009
.NET NameValueCollection DataTypes
A NameValueCollection is similar to a .NET Hash Table in that it can store items in key/value pairs and allows you to retrieve items by specifying either the Key or index. In fact, NameValueCollections use the hash table and hash table algorithms for their underlying data structures.
Unlike a hash table that can store any type of object as its key or value, NameValueCollections can only store string values. However, a NameValueCollection can store multiple strings values for each key. Because NameValueCollections use the hash table algorithms, they are slower performance wise than hash tables.
A NameValueCollection also has methods to return a collection of all keys, all values, add and remove items and to get an enumerator so you can enumerate through the collection.
Unlike a hash table that can store any type of object as its key or value, NameValueCollections can only store string values. However, a NameValueCollection can store multiple strings values for each key. Because NameValueCollections use the hash table algorithms, they are slower performance wise than hash tables.
A NameValueCollection also has methods to return a collection of all keys, all values, add and remove items and to get an enumerator so you can enumerate through the collection.
Friday, March 13, 2009
How to change default button of ASP.NET Page
ASP.Net 2.0 has a new feature of setting default button of a asp.net page.
Now you can set initial focus on your form and also set a default button (for when pressing enter) by setting 2 attributes on your form tag:
defaultbutton="Button1" defaultfocus="TextBox1"
This will add JavaScript to set focus on TextBox1 and set the Button1 as the default button for when a user presses enter on the web form.
This is very neat, but when using master pages you don't have access to the form tag. As of any property, you can also set it at the code behind, but you need a little trick. Since ASP.NET uses javascript to set the focus and the default button, you have to specify the client id of the controls, rather than the server ids:
Page.Form.DefaultButton = Button1.UniqueID;
Page.Form.DefaultFocus = TextBox1.ClientID;
Happy Programming!!
Now you can set initial focus on your form and also set a default button (for when pressing enter) by setting 2 attributes on your form tag:
defaultbutton="Button1" defaultfocus="TextBox1"
This will add JavaScript to set focus on TextBox1 and set the Button1 as the default button for when a user presses enter on the web form.
This is very neat, but when using master pages you don't have access to the form tag. As of any property, you can also set it at the code behind, but you need a little trick. Since ASP.NET uses javascript to set the focus and the default button, you have to specify the client id of the controls, rather than the server ids:
Page.Form.DefaultButton = Button1.UniqueID;
Page.Form.DefaultFocus = TextBox1.ClientID;
Happy Programming!!
Thursday, March 12, 2009
How to get SPUser name from User Id
Sometimes we get uniques user id from sharepoint but the requirement is for name.
This can be done in one simple line:
using (SPSite site=new SPSite(siteurl))
{
using (SPWeb web=site.OpenWeb())
{
string userName= web.AllUsers.GetByID(Convert.ToInt32(userid)).Name;
}
}
Line number 5 actually gets the user name by searching all users in the 'web' scope by searching userId.
This can be done in one simple line:
using (SPSite site=new SPSite(siteurl))
{
using (SPWeb web=site.OpenWeb())
{
string userName= web.AllUsers.GetByID(Convert.ToInt32(userid)).Name;
}
}
Line number 5 actually gets the user name by searching all users in the 'web' scope by searching userId.
Wednesday, March 11, 2009
Disposing SPWeb and SPSite objects
What happens if a SPWeb object is not disposed?
Each SPWeb and SPSite object holds a reference to a SPRequest object which holds a reference to a SharePoint COM object that is responsible to communicate with the backend SQL server.
Disposing a SPWeb object will not actually remove the SPWeb object from memory (actually the .NET framework does not allow to remove any object from memory in a deterministic way) but it will call a method of the SPWeb object which causes the COM object to close the connection to the SQL server and to release its allocated memory.
That means the connection to the backend SQL server will remain open from the moment the SPRequest object has been created till the SPWeb object is disposed.
After the dispose only the small managed SPWeb and SPRequest objects remain in memory which do not create a big memory overhead. They are removed by the dot net framework through garbage collection later as with any other managed object as soon as no references to the object exist any more.
In case that the SPWeb object is not disposed when it is no longer used, then the connection to the SQL server will stay open and the memory allocated by the COM object will stay in memory as the COM object has not been asked to close the connection and to release the memory.
Each connection to the database requires a tcp port for the communication. Per default only 5000-1023 = 3977 ports are available. Which means on a single machine per default you cannot have more than 3977 open connections to other applications. Be aware that this is the number for all processes. Not just a single application pool.
So beside the fact that not disposing SPWeb and SPSite will lead to a higher memory consumption which finally can lead to out of memory exceptions the machine might also run out of TCP ports which would lead to lots of other problems - potentially also in other applications on the same server.
When should SPWeb and SPSite objects be disposed?
You should dispose a SPWeb or SPSite object after the last access to a child object of this object. Be aware that a sub site (SPWeb) is not a child object. But (e.g.) a list or a folder or list item is a child object for this scenario.
When should I dispose SPSite.RootWeb?
When SPSite.RootWeb is first accessed it creates an SPWeb object using SPSite.OpenWeb and stores a reference in an internal variable. Further accesses to SPSite.RootWeb are then satisfied by returning a reference to the earlier created object. In case the RootWeb object has been disposed it will create a new one using OpenWeb as for the initial access.
That means we have a single SPWeb object per SPSite object even if we access SPSite.RootWeb multiple times. Creating a SPWeb object is an expensive operation as it requires the instantiation of a COM object, a database communication to download the info about the SPWeb object and so on. That means disposing the RootWeb object after every single access to it can affect the performance of the site - especially if you have many different places in your project that do the same for the same SPSite object. So ensure to dispose the RootWeb object only after the last access to it in your code whereever the logic of the code allows to determine this.
Also please do not dispose the RootWeb property of SPContext.Current.Site. This object is used in many different places in SharePoint and you should not dispose it. It will automatically be cleaned up when the request finishes.
-----------------------------------------------------------------------
Dispose of objects which do not belong to the method?
In general SPSite and SPWeb objects should be disposed in the same method they get allocated. That's the best method to ensure that no disposed can be missed and to ensure that a dispose does not occur for an object that will be used later.
I have seen several cases where custom code disposed SPWeb and SPSite objects incorrectly.
A very common scenario is the following:
...
using (SPSite mySite = SPContext.Current.Site)
{
...
}
...
Using "using" statements is a very nice method to ensure that at the end the object being used gets properly disposed. The problem in the code above is that SPContext.Current.Site and SPContext.Current.Web are not allowed to be disposed! Using successfully hides the dispose statement here. "Using" allows a nice structuring of the code so users often use it without thinking about the side effects.
If you plan to use a using statement with SPContext you need to code it like this:
...
using (SPSite mySite = new SPSite(SPContext.Current.Site.ID))
{
...
}
...
This method will ensure that a new independent SPSite object is created which you then can dispose without side effects on other code using the SPSite object bound to the current SPContext object.
-----------------------------------------------------------------------
Another common error is to dispose an SPSite or SPWeb object in a event receiver:
public override void ItemCheckingOut(SPItemEventProperties properties)
{
...
// incorrect dispose of SPWeb
using (SPWeb web = properties.ListItem.Web)
{
}
...
// incorrect dispose of SPSite
using (SPWeb site = properties.ListItem.Web.Site)
{
}
...
}
After executing our code other event receivers will receive an object where the underlaying SPWeb and/or SPSite object has been disposed. This can lead to exceptions.
-----------------------------------------------------------------------
// Do not do this. Dispose() is automatically called on SPWeb.
using( SPWeb web = SPControl.GetContextWeb(HttpContext.Current)) { ... }
SPContext objects are managed by the SharePoint framework and should not be explicitly disposed in your code. This is true also for the SPSite and SPWeb objects returned by SPContext.Site, SPContext.Current.Site, SPContext.Web, and SPContext.Current.Web.
You must be cautious and aware of what the runtime is doing whenever you combine SharePoint object model calls on the same line. Leaks arising from this scenario are among the hardest to find.
Each SPWeb and SPSite object holds a reference to a SPRequest object which holds a reference to a SharePoint COM object that is responsible to communicate with the backend SQL server.
Disposing a SPWeb object will not actually remove the SPWeb object from memory (actually the .NET framework does not allow to remove any object from memory in a deterministic way) but it will call a method of the SPWeb object which causes the COM object to close the connection to the SQL server and to release its allocated memory.
That means the connection to the backend SQL server will remain open from the moment the SPRequest object has been created till the SPWeb object is disposed.
After the dispose only the small managed SPWeb and SPRequest objects remain in memory which do not create a big memory overhead. They are removed by the dot net framework through garbage collection later as with any other managed object as soon as no references to the object exist any more.
In case that the SPWeb object is not disposed when it is no longer used, then the connection to the SQL server will stay open and the memory allocated by the COM object will stay in memory as the COM object has not been asked to close the connection and to release the memory.
Each connection to the database requires a tcp port for the communication. Per default only 5000-1023 = 3977 ports are available. Which means on a single machine per default you cannot have more than 3977 open connections to other applications. Be aware that this is the number for all processes. Not just a single application pool.
So beside the fact that not disposing SPWeb and SPSite will lead to a higher memory consumption which finally can lead to out of memory exceptions the machine might also run out of TCP ports which would lead to lots of other problems - potentially also in other applications on the same server.
When should SPWeb and SPSite objects be disposed?
You should dispose a SPWeb or SPSite object after the last access to a child object of this object. Be aware that a sub site (SPWeb) is not a child object. But (e.g.) a list or a folder or list item is a child object for this scenario.
When should I dispose SPSite.RootWeb?
When SPSite.RootWeb is first accessed it creates an SPWeb object using SPSite.OpenWeb and stores a reference in an internal variable. Further accesses to SPSite.RootWeb are then satisfied by returning a reference to the earlier created object. In case the RootWeb object has been disposed it will create a new one using OpenWeb as for the initial access.
That means we have a single SPWeb object per SPSite object even if we access SPSite.RootWeb multiple times. Creating a SPWeb object is an expensive operation as it requires the instantiation of a COM object, a database communication to download the info about the SPWeb object and so on. That means disposing the RootWeb object after every single access to it can affect the performance of the site - especially if you have many different places in your project that do the same for the same SPSite object. So ensure to dispose the RootWeb object only after the last access to it in your code whereever the logic of the code allows to determine this.
Also please do not dispose the RootWeb property of SPContext.Current.Site. This object is used in many different places in SharePoint and you should not dispose it. It will automatically be cleaned up when the request finishes.
-----------------------------------------------------------------------
Dispose of objects which do not belong to the method?
In general SPSite and SPWeb objects should be disposed in the same method they get allocated. That's the best method to ensure that no disposed can be missed and to ensure that a dispose does not occur for an object that will be used later.
I have seen several cases where custom code disposed SPWeb and SPSite objects incorrectly.
A very common scenario is the following:
...
using (SPSite mySite = SPContext.Current.Site)
{
...
}
...
Using "using" statements is a very nice method to ensure that at the end the object being used gets properly disposed. The problem in the code above is that SPContext.Current.Site and SPContext.Current.Web are not allowed to be disposed! Using successfully hides the dispose statement here. "Using" allows a nice structuring of the code so users often use it without thinking about the side effects.
If you plan to use a using statement with SPContext you need to code it like this:
...
using (SPSite mySite = new SPSite(SPContext.Current.Site.ID))
{
...
}
...
This method will ensure that a new independent SPSite object is created which you then can dispose without side effects on other code using the SPSite object bound to the current SPContext object.
-----------------------------------------------------------------------
Another common error is to dispose an SPSite or SPWeb object in a event receiver:
public override void ItemCheckingOut(SPItemEventProperties properties)
{
...
// incorrect dispose of SPWeb
using (SPWeb web = properties.ListItem.Web)
{
}
...
// incorrect dispose of SPSite
using (SPWeb site = properties.ListItem.Web.Site)
{
}
...
}
After executing our code other event receivers will receive an object where the underlaying SPWeb and/or SPSite object has been disposed. This can lead to exceptions.
-----------------------------------------------------------------------
// Do not do this. Dispose() is automatically called on SPWeb.
using( SPWeb web = SPControl.GetContextWeb(HttpContext.Current)) { ... }
SPContext objects are managed by the SharePoint framework and should not be explicitly disposed in your code. This is true also for the SPSite and SPWeb objects returned by SPContext.Site, SPContext.Current.Site, SPContext.Web, and SPContext.Current.Web.
You must be cautious and aware of what the runtime is doing whenever you combine SharePoint object model calls on the same line. Leaks arising from this scenario are among the hardest to find.
Monday, March 9, 2009
How to customization status of a file, removing any customization
Hi ,
This post deals with checking the customization status of any sharepoint file and if file is found to be customized then to remove its customiztion and reverting back to template file.
using System;
using Microsoft.SharePoint;
namespace CustomizationCheck {
class Program {
static void Main (string[] args) {
using (SPSite siteCollection = new SPSite("http://sitename")) {
using (SPWeb site = siteCollection.RootWeb) {
SPFile file = site.GetFile("default.aspx");
// if file is customized, revert to underlying template file
if (file.CustomizedPageStatus == SPCustomizedPageStatus.Customized)
file.RevertContentStream();
} // SPWeb using statement
} // SPSite using statement
} // method “Main”
}
}
This post deals with checking the customization status of any sharepoint file and if file is found to be customized then to remove its customiztion and reverting back to template file.
using System;
using Microsoft.SharePoint;
namespace CustomizationCheck {
class Program {
static void Main (string[] args) {
using (SPSite siteCollection = new SPSite("http://sitename")) {
using (SPWeb site = siteCollection.RootWeb) {
SPFile file = site.GetFile("default.aspx");
// if file is customized, revert to underlying template file
if (file.CustomizedPageStatus == SPCustomizedPageStatus.Customized)
file.RevertContentStream();
} // SPWeb using statement
} // SPSite using statement
} // method “Main”
}
}
Wednesday, March 4, 2009
How to stop ItemUpdate fire from ItemListener
Many tile it happens that we update an item and call custom Item added event listener.
Now suppose , if we have to update some item of list in the event listner so the update event will get fire again from the listener and it will be a never endin g loop..
In order to solve that, there is a one line solution...
In the ItemUpdated event,
put the following code:
this.DisableEventFire();
then update the list and again enable the same
this.EnableventFire();
This will solve the issue.
Now suppose , if we have to update some item of list in the event listner so the update event will get fire again from the listener and it will be a never endin g loop..
In order to solve that, there is a one line solution...
In the ItemUpdated event,
put the following code:
this.DisableEventFire();
then update the list and again enable the same
this.EnableventFire();
This will solve the issue.
Tuesday, March 3, 2009
How to set Item Level Permission in to Sharepoint List
Hi,
Today I will discuss how to revoke Item level permission and how to grant Item Level permission on a sharepoint list to a user.
Before discussing the code, I would like to tell you something about some properties used in the code:
SPList.RoleAssignments Property :
Gets the collection of role assignments for the list.
Namespace: Microsoft.SharePoint
Assembly: Microsoft.SharePoint (in microsoft.sharepoint.dll)
SPRoleAssignment.RoleDefinitionBindings Property : Gets the collection of role definition bindings for the role assignment.
Namespace: Microsoft.SharePoint
Assembly: Microsoft.SharePoint (in microsoft.sharepoint.dll)
SPPrincipal Class :
Represents a user or group that can be assigned permissions in Windows SharePoint Services to control security.
Namespace: Microsoft.SharePoint
Assembly: Microsoft.SharePoint (in microsoft.sharepoint.dll)
I have written a function that will take the following parameters:
1. string Site url
2. string Library name
3. string Old user name (format : <domainname>\<username>
4. string new user name (format : <domainname>\<username>
My whole intension of function is to revoke permission of the item from old user and assign it to new user. You may or may not require the new user parameter if you are only revoking access.
public static void SetItemPermission(string SitePath, string LibName, string OldUser, string NewUser)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite WebApp = new SPSite(SitePath))
{
using (SPWeb Site = WebApp.OpenWeb())
{
SPList list = Site.Lists[LibName];
SPQuery newSPQuery = new SPQuery();
newSPQuery.Query = "<where><contains><fieldref name="\">" +
"<value type="\">" + OldUser + "</value>" + "</contains></where>";
try{
SPListItemCollection listItemCol = list.GetItems(newSPQuery);
if (listItemCol.Count > 0)
{
SPUser user = null, _newUser = null;
SPRoleAssignment role = null;
foreach (SPListItem item in listItemCol)
{
user = Site.Users[OldUser];
SPPrincipal principal = (SPPrincipal)user;
item.RoleAssignments.Remove(principal);
role = new SPRoleAssignment(NewUser, "", "", "");
role.RoleDefinitionBindings.Add(Site.RoleDefinitions["Contribute"]);
item.RoleAssignments.Add(role);
}
item.SystemUpdate(false);
}
}}catch(Exception ex){}
}
}
});
}
#endregion
Today I will discuss how to revoke Item level permission and how to grant Item Level permission on a sharepoint list to a user.
Before discussing the code, I would like to tell you something about some properties used in the code:
SPList.RoleAssignments Property :
Gets the collection of role assignments for the list.
Namespace: Microsoft.SharePoint
Assembly: Microsoft.SharePoint (in microsoft.sharepoint.dll)
SPRoleAssignment.RoleDefinitionBindings Property : Gets the collection of role definition bindings for the role assignment.
Namespace: Microsoft.SharePoint
Assembly: Microsoft.SharePoint (in microsoft.sharepoint.dll)
SPPrincipal Class :
Represents a user or group that can be assigned permissions in Windows SharePoint Services to control security.
Namespace: Microsoft.SharePoint
Assembly: Microsoft.SharePoint (in microsoft.sharepoint.dll)
I have written a function that will take the following parameters:
1. string Site url
2. string Library name
3. string Old user name (format : <domainname>\<username>
4. string new user name (format : <domainname>\<username>
My whole intension of function is to revoke permission of the item from old user and assign it to new user. You may or may not require the new user parameter if you are only revoking access.
public static void SetItemPermission(string SitePath, string LibName, string OldUser, string NewUser)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite WebApp = new SPSite(SitePath))
{
using (SPWeb Site = WebApp.OpenWeb())
{
SPList list = Site.Lists[LibName];
SPQuery newSPQuery = new SPQuery();
newSPQuery.Query = "<where><contains><fieldref name="\">" +
"<value type="\">" + OldUser + "</value>" + "</contains></where>";
try{
SPListItemCollection listItemCol = list.GetItems(newSPQuery);
if (listItemCol.Count > 0)
{
SPUser user = null, _newUser = null;
SPRoleAssignment role = null;
foreach (SPListItem item in listItemCol)
{
user = Site.Users[OldUser];
SPPrincipal principal = (SPPrincipal)user;
item.RoleAssignments.Remove(principal);
role = new SPRoleAssignment(NewUser, "", "", "");
role.RoleDefinitionBindings.Add(Site.RoleDefinitions["Contribute"]);
item.RoleAssignments.Add(role);
}
item.SystemUpdate(false);
}
}}catch(Exception ex){}
}
}
});
}
#endregion
Subscribe to:
Posts (Atom)