A must read article on web site performance
http://developer.yahoo.com/performance/rules.html
Will try to pen down all learnings, troubleshoots and gotchas in what ever technology I come across.
Tuesday, October 11, 2011
Friday, September 16, 2011
SEO Optimizations using Rewrite.
Came across this nice link from Scott Guthrie..
Let's assume that by default /pages/default.aspx is going to be called whenever a user types the domain name on the URL. The below are different cases where it demonstrates that the search indexes by different search engines identifies each of these as different resources and hence reducing the search rankings.
4 Really Common SEO Problems Your Sites Might Have
SEO Problem #1: Default Document
http://mysite.com
http://mysite.com/pages/default.aspx
SEO Problem #2: Different URL Casings
http://mysite.com/Pages/Default.aspx
http://mysite.com/pages/default.aspx
SEO Problem #3: Trailing Slashes
http://mysite.com
http://mysite.com/
SEO Problem #4: Canonical Host Names
http://mysite.com/pages/default.aspx
http://www.mysite.com/pages/default.aspx
4 Really Common SEO Problems Your Sites Might Have
SEO Problem #1: Default Document
http://mysite.com
http://mysite.com/pages/default.aspx
SEO Problem #2: Different URL Casings
http://mysite.com/Pages/Default.aspx
http://mysite.com/pages/default.aspx
SEO Problem #3: Trailing Slashes
http://mysite.com
http://mysite.com/
SEO Problem #4: Canonical Host Names
http://mysite.com/pages/default.aspx
http://www.mysite.com/pages/default.aspx
Scott, explains in detail how we can increase the search relevancy by fixing these using the URL Rewrite module to either rewrite or redirect the users to a standard naming..
Read on...
Thursday, June 16, 2011
8 Steps to Create & Configure MySite in SharePoint 2010
Following are the steps to create and configure the MySite for your SharePoint 2010 Farm
- Create a Web Application with Classic Mode
- Create a new Site Collection using the MySite Host Template under Enterprise tab.
- Configure the User Profile Service Application > Setup My Site.
- Set the Preferred Search Site URL & Personal Site URL format.
- Add Managed Path "Personal" as a wildcard inclusion through the Manage Web Applications > My Site > Managed Paths.
- Switch ON the Self Service Site Collection management through the Manage Web Applications > My Site > Self Service Site creation
- On browsing to personal site for the first time the site is created.
- Have fun! :)
Tuesday, May 10, 2011
Production Setup of SharePoint 2010 and SSRS Load balanced with NLB
Production Setup:
- Two Web Front Ends (Network Load balanced) - No Central Administration
- Two Application Servers (Includes SharePoint, Power Pivot and SSRS Servers - Network Load balanced) - Both Servers contain Central Administration
- Clustered Database (Active-Passive Mode)
- SAN (Later switched to NAS) for storage of terabytes of Images. Product involves storing a lot of images.
All machines were Windows Server 2008 R2 with imaginably very high configuration on memory and hard drive.
SharePoint does not require you to load balance the Application Server, however in this specific case the requirement was to have high availability of the application and provision for scaling later.
First configure the DB in a clustered mode. This was already done by the DBA, so I will not cover it here.
Next, configure the Report Server in a scale out mode over a NLB
To setup and configure the SharePoint, we followed the steps mentioned in the below article with a few exceptions (Configuring Search was not required).
We made sure that all the Service applications (Excel, Power Pivot & Secured Store Service) were provisioned on both the Application Servers.
Make sure to have only the required services in the WFE. You can turn off all the Service Applications that are provisioned on the Application Servers.
Next, setup the Power Pivot on both the Application Server and re-configure the Power Pivot Service Application from the Central Administration.
Once the Configuration was done, most of the steps were custom.
Few things that is worth of mentioning:
- Ensure that your domain name and web site names are not the same. We had a very hard time reverting it as users internally to the company were not able to use the Web Site. The reason, was all the requests to the site was going to the Domain Controller instead.
- When you are creating a Web Application, use the website name for Public URL Ex: http://mywebsite.domain.com instead of the default, Application Server name (filled by default). We could not find a way to revert this.
- Ensure to make appropriate DNS entries so that the web site is really internet facing. Your administrator may want to make entries in the Name server, to map the website name to the local load balancing web server, so that users (employees) within the domain need not go through internet.
Thursday, May 5, 2011
Can't find my SharePoint Web page on IIS?
Coming from a background of ASP.net, we are used to going to the IIS Manager and locating a web page file. In SharePoint, try finding it. You will be surprised. We usually map the URL relative to the Application directory of the WFE.
When you create a new Web Application in SharePoint it creates an entry in the IIS with the application by default being hosted on the Physical Directory C:\inetpub\wwwroot\wss\VirtualDirectories\
All Standard Pages/Pages that you created in the SharePoint Console, ideally should have been placed in this directory, but, instead SharePoint stores them in the Content database.
Then you must be wondering how SharePoint manages to find the correct page through the URL.
ASP.Net came up with a new concept of VirtualPathProvider. To allow users to implement custom storage of the files (web pages) without affecting the way users access web pages. SharePoint has provided a custom implementation through SPVirtualPathProvider that connects the URL with the appropriate page from the Content Database.
The SPVirtualPathProvider class works together with another class named the SPPageParserFilter to supply processing instructions to the ASP.NET page parser. For example, the SPPageParserFilter component controls whether the ASP.NET page parser compiles the ASP.NET page into an assembly DLL or whether it processes the page in a no-compile mode that is introduced with ASP.NET 2.0
Not all standard pages come from SharePoint Content database. Some pages are hosted within the SharePoint root folder. C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\
SPVirtualPathProvider will know from where a particular page has to be picked up from (File System vs. Database). These kinds of pages are called as Ghosted Pages. The pages that come from Content database are called UnGhosted pages. These are customized pages of the standard pages.
SharePoint version of the life cycle is depicted in the below image. They integrate with the ASP.Net runtime seamlessly by adding the SPHttpApplication (HttpApplication replacement for the ASP.net) containing a Module SPRequestModule with a couple of common ASP.Net modules. This finally uses the SPHttpHandler (SharePoint implementation of HttpHandler) to process requests.
A quick view of the IIS brings us to a couple of Virtual Directories of a SharePoint web application. If you follow the Physical path of these they point to the Root folder.
When you create a new Web Application in SharePoint it creates an entry in the IIS with the application by default being hosted on the Physical Directory C:\inetpub\wwwroot\wss\VirtualDirectories\
All Standard Pages/Pages that you created in the SharePoint Console, ideally should have been placed in this directory, but, instead SharePoint stores them in the Content database.
Then you must be wondering how SharePoint manages to find the correct page through the URL.
ASP.Net came up with a new concept of VirtualPathProvider. To allow users to implement custom storage of the files (web pages) without affecting the way users access web pages. SharePoint has provided a custom implementation through SPVirtualPathProvider that connects the URL with the appropriate page from the Content Database.
The SPVirtualPathProvider class works together with another class named the SPPageParserFilter to supply processing instructions to the ASP.NET page parser. For example, the SPPageParserFilter component controls whether the ASP.NET page parser compiles the ASP.NET page into an assembly DLL or whether it processes the page in a no-compile mode that is introduced with ASP.NET 2.0
Not all standard pages come from SharePoint Content database. Some pages are hosted within the SharePoint root folder. C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\
SPVirtualPathProvider will know from where a particular page has to be picked up from (File System vs. Database). These kinds of pages are called as Ghosted Pages. The pages that come from Content database are called UnGhosted pages. These are customized pages of the standard pages.
SharePoint version of the life cycle is depicted in the below image. They integrate with the ASP.Net runtime seamlessly by adding the SPHttpApplication (HttpApplication replacement for the ASP.net) containing a Module SPRequestModule with a couple of common ASP.Net modules. This finally uses the SPHttpHandler (SharePoint implementation of HttpHandler) to process requests.
Global.asax would contain a directive as
<@Application Inherits="Microsoft.SharePoint.ApplicationRuntime.SPHttpApplication" >
Http Module and Http Handers will be registered with the application through the Web.Config.
A quick view of the IIS brings us to a couple of Virtual Directories of a SharePoint web application. If you follow the Physical path of these they point to the Root folder.
Note: The image is from the MOSS. However, they are pretty much the same with a few additions in SharePoint 2010.
- _vit_bin : Provides Windows SharePoint Services with a way to expose DLLs and .asmx Web service files at a path within the URL space of a Web application.
- _controltemplates : Provides a repository for deploying ASP.NET user controls that can be used within pages.
- _wpresources : Provides a repository for resource files that are deployed along with Web Parts.
- layouts : Provides the repository for application pages.
An application page, such as settings.aspx, can be accessed by adding its relative path within the _layouts directory to the end of a site’s URL
http://Litwareinc.com/_layouts/settings.aspx
http://Litwareinc.com/sites/Vendors/_layouts/settings.aspx
http://Litwareinc.com:1001/sites/Accounting/_layouts/settings.aspx
Labels:
IIS,
SharePoint 2010,
Virtual Directories,
VirtualPathProvider
Wednesday, April 6, 2011
Limitation on SharePoint 2010
Just came across a nice article that lists all the limitations in SharePoint 2010.
http://sharepointgadget.blogspot.com/2010/05/limits-in-sharepoint-2010.html
http://sharepointgadget.blogspot.com/2010/05/limits-in-sharepoint-2010.html
Saturday, March 12, 2011
Restricted Elevation in SharePoint
There are times when we would need to perform certain operations that would require elevated privileges. If your IT team is not willing to allow you to provide the necessary actions on the system account or the application pool account with all the rights, but instead use appropriate service accounts shared by other application then you would do something like this.
SPUser userImpersonated = Web.Users[@"mydomain\impersonatedUser"];
SPSite site = new SPSite("http://mywebsite", userImpersonated.UserToken);
using (SPWeb web = site.OpenWeb())
{
// This is the section where you will use the impersonated token to do the elevated job
lblMessage.Text = web.CurrentUser.LoginName;
}
instead of.
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(url))
{
using (SPWeb web = site.OpenWeb())
{
// This is the section where you will do the job that requires elevated permissions
}
}
});
SPUser userImpersonated = Web.Users[@"mydomain\impersonatedUser"];
SPSite site = new SPSite("http://mywebsite", userImpersonated.UserToken);
using (SPWeb web = site.OpenWeb())
{
// This is the section where you will use the impersonated token to do the elevated job
lblMessage.Text = web.CurrentUser.LoginName;
}
instead of.
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(url))
{
using (SPWeb web = site.OpenWeb())
{
// This is the section where you will do the job that requires elevated permissions
}
}
});
Thursday, February 17, 2011
Excel Services with Custom MDX Query
Yet another interesting situation where we had to display an Report on Excel and put it on SharePoint Power pivot gallery. We selected the Cube database and dragged in a few dimensions and Measures along with a few slicers. The query that was auto generated was not very optimized.
The report was to show data only for last one week. One of the slicer "Week Starting Date" was to have dates for the last one month only.
We had to use some hidden filters to ensure that we show only part of the data. i.e. only last 4 weeks data. There are few ways (Slicer Settings) where we can visually indicate that Items that do not have data should be disabled (will be shown) and also there is a way to move those items to the end of the slicer. There is no way of removing that altogether.
In such situations we can write a custom query to only fetch data with Week Starting Dates that is within the last one month range. This also improves the performance because of the optimized query against the Cubes.
Excel do not provide a direct way to update the query. There are a few Adins/products that aid to this, like Vivid http://www.varigence.com/products/vivid/features/navigation that will come into handy.
Another approach could be to use an ODC File where you can embed the MDX query. I am attaching a sample ODC file. Pay close attention to the highlighted section.
<html xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=Content-Type content="text/x-ms-odc; charset=utf-8">
<meta name=ProgId content=ODC.Cube>
<meta name=SourceType content=OLEDB>
<meta name=Catalog content=CubeDB>
<meta name=Table content=CDW>
<title>sqlserver2008r2 CubeDB CDW</title>
<xml id=docprops><o:DocumentProperties
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns="http://www.w3.org/TR/REC-html40">
<o:Name>sqlserver2008r2 CubeDB CDW</o:Name>
</o:DocumentProperties>
</xml><xml id=msodc><odc:OfficeDataConnection
xmlns:odc="urn:schemas-microsoft-com:office:odc"
xmlns="http://www.w3.org/TR/REC-html40">
<odc:Connection odc:Type="OLEDB">
<odc:ConnectionString>Provider=MSOLAP.4;Password=password;Persist Security Info=True;Data Source=Server\sqlserver2008r2;Initial Catalog=CubeDB</odc:ConnectionString>
<odc:CommandType>MDX</odc:CommandType>
<odc:CommandText>SELECT
{ [Measures].[Sales Amount],
[Measures].[Tax Amount] } ON 0,
{ [Date].[Fiscal].[Fiscal Year].&[2002],
[Date].[Fiscal].[Fiscal Year].&[2003] } ON 1
FROM [Adventure Works]
WHERE ( [Sales Territory].[Southwest] )
</odc:CommandText>
</odc:Connection>
</odc:OfficeDataConnection>
</xml>
<style>
<!--
.ODCDataSource
{
behavior: url(dataconn.htc);
}
-->
</style>
</head>
</html>
The report was to show data only for last one week. One of the slicer "Week Starting Date" was to have dates for the last one month only.
We had to use some hidden filters to ensure that we show only part of the data. i.e. only last 4 weeks data. There are few ways (Slicer Settings) where we can visually indicate that Items that do not have data should be disabled (will be shown) and also there is a way to move those items to the end of the slicer. There is no way of removing that altogether.
In such situations we can write a custom query to only fetch data with Week Starting Dates that is within the last one month range. This also improves the performance because of the optimized query against the Cubes.
Excel do not provide a direct way to update the query. There are a few Adins/products that aid to this, like Vivid http://www.varigence.com/products/vivid/features/navigation that will come into handy.
Another approach could be to use an ODC File where you can embed the MDX query. I am attaching a sample ODC file. Pay close attention to the highlighted section.
<html xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=Content-Type content="text/x-ms-odc; charset=utf-8">
<meta name=ProgId content=ODC.Cube>
<meta name=SourceType content=OLEDB>
<meta name=Catalog content=CubeDB>
<meta name=Table content=CDW>
<title>sqlserver2008r2 CubeDB CDW</title>
<xml id=docprops><o:DocumentProperties
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns="http://www.w3.org/TR/REC-html40">
<o:Name>sqlserver2008r2 CubeDB CDW</o:Name>
</o:DocumentProperties>
</xml><xml id=msodc><odc:OfficeDataConnection
xmlns:odc="urn:schemas-microsoft-com:office:odc"
xmlns="http://www.w3.org/TR/REC-html40">
<odc:Connection odc:Type="OLEDB">
<odc:ConnectionString>Provider=MSOLAP.4;Password=password;Persist Security Info=True;Data Source=Server\sqlserver2008r2;Initial Catalog=CubeDB</odc:ConnectionString>
<odc:CommandType>MDX</odc:CommandType>
<odc:CommandText>SELECT
{ [Measures].[Sales Amount],
[Measures].[Tax Amount] } ON 0,
{ [Date].[Fiscal].[Fiscal Year].&[2002],
[Date].[Fiscal].[Fiscal Year].&[2003] } ON 1
FROM [Adventure Works]
WHERE ( [Sales Territory].[Southwest] )
</odc:CommandText>
</odc:Connection>
</odc:OfficeDataConnection>
</xml>
<style>
<!--
.ODCDataSource
{
behavior: url(dataconn.htc);
}
-->
</style>
</head>
</html>
Labels:
Custom MDX,
Data Refresh,
Excel Service Application,
Slicers,
SSAS
Monday, February 14, 2011
Securing your LDAP Membership Provider
There are situations where you want to have Forms based Authentication in SharePoint. That is when you will choose the Claims based Authentication on the Web Application.
We had a requirement where we need to classify two kinds of users Employees and Clients. For a certain reason we had to chose Active Directory as the user store for both kinds of users. We could not reuse the Active Directory of the Employees for the Client users. Hence, we ended creating another domain just for the client users.
When you are using a LdapProvider if the Application Pool account do not have the rights to perform an LDAP request on the Active Directory then you will need to specify two attributes connectionUsername & connectionPassword in the Ldap membership provider of the web.config. This is where you would not want to keep the connectionPassword in plain text. Below I have given a simple implementation to Encrypt and store the password and how you could use a method to retrieve the password at run time.
The web.config of the Web Application, Central Administration & Security Token Service will look something like this with a connectionPassword having the encrypted string.
<membership defaultProvider="CustomLdapProvider">
<providers>
<add name="ClientsADMembershipProvider" type="Microsoft.Office.Server.Security.LDAPMembershipProvider, Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71E9BCE111E9429C" server="dc.clientsdomain.com" port="389" useSSL="false" userDNAttribute="distinguishedName" userNameAttribute="sAMAccountName" userContainer="CN=Users,DC=domain,DC=com" userObjectClass="person" userFilter="(|(ObjectCategory=group)(ObjectClass=person))" scope="Subtree" otherRequiredUserAttributes="sn,givenname,cn" connectionUsername="clientsdomain\administrator" connectionPassword="SDJFSew98234DFJ889==" />
<add name="EmployeesADMembershipProvider" type="Microsoft.Office.Server.Security.LDAPMembershipProvider, Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71E9BCE111E9429C" server="dc.employeesdomain.com" port="389" useSSL="false" userDNAttribute="distinguishedName" userNameAttribute="sAMAccountName" userContainer="CN=Users,DC=domain,DC=com" userObjectClass="person" userFilter="(|(ObjectCategory=group)(ObjectClass=person))" scope="Subtree" otherRequiredUserAttributes="sn,givenname,cn" connectionUsername="employeesdomain\administrator" connectionPassword="SL43Sew982342KLSDF==" />
<add name="CustomLdapProvider" type="Project.CustomLdapProvider, Project, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8027a17523a78ae328" />
</providers>
</membership>
The partial implementation of CustomLdapProvider will be something like below:
public class CustomLdapProvider : MembershipProvider
{
private static LdapMembershipProvider _employeesProvider = null;
private static LdapMembershipProvider _clientsProvider = null;
private LdapMembershipProvider GetMembershipProvider(string providerName)
{
LdapMembershipProvider provider = new LdapMembershipProvider();
// In SharePoint when your login page is coming from Layouts folder, HttpContext.Current is returning null. Hence the next line.
//Configuration config = WebConfigurationManager.OpenWebConfiguration(HttpContext.Current.Request.ApplicationPath);
Configuration config = WebConfigurationManager.OpenWebConfiguration(@"~/web.config");
MembershipSection section = (MembershipSection)config.GetSection("system.web/membership");
ProviderSettings providerSettings = section.Providers[providerName];
NameValueCollection param = providerSettings.Parameters;
param["connectionPassword"] = Utility.Decryption(param["connectionPassword"], true);
provider.Initialize(providerName, param);
return provider;
}
private MembershipProvider EmployeesProvider
{
get
{
if (_employeeProvider == null)
{
_employeeProvider = GetMembershipProvider("EmployeesADMembershipProvider");
}
return (MembershipProvider)_employeesProvider;
}
}
private MembershipProvider ClientsProvider
{
get
{
if (_clientsProvider== null)
{
_clientsProvider = GetMembershipProvider("ClientsADMembershipProvider");
}
return (MembershipProvider)_clientsProvider;
}
}
// Override all the membership provider and use the appropriate Membership provider to call the overloads.
public override bool ValidateUser(string name, string password)
{
// name = loginid@clientsdomain.com / loginid@employeesdomain.com
// Extract the domain name and based on the domain connect to the appropriate Membership Provider (EmployeesProvider, ClientsProvider) and call the ValidateUser.
// Ex: ClientsProvider.ValidateUser(name, password)
}
}
I am sure this will be quite useful in implementing Forms Based Authentication in SharePoint when you have to work against an LDAP Provider and do not want to compromise on the connection string.
We had a requirement where we need to classify two kinds of users Employees and Clients. For a certain reason we had to chose Active Directory as the user store for both kinds of users. We could not reuse the Active Directory of the Employees for the Client users. Hence, we ended creating another domain just for the client users.
When you are using a LdapProvider if the Application Pool account do not have the rights to perform an LDAP request on the Active Directory then you will need to specify two attributes connectionUsername & connectionPassword in the Ldap membership provider of the web.config. This is where you would not want to keep the connectionPassword in plain text. Below I have given a simple implementation to Encrypt and store the password and how you could use a method to retrieve the password at run time.
The web.config of the Web Application, Central Administration & Security Token Service will look something like this with a connectionPassword having the encrypted string.
<membership defaultProvider="CustomLdapProvider">
<providers>
<add name="ClientsADMembershipProvider" type="Microsoft.Office.Server.Security.LDAPMembershipProvider, Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71E9BCE111E9429C" server="dc.clientsdomain.com" port="389" useSSL="false" userDNAttribute="distinguishedName" userNameAttribute="sAMAccountName" userContainer="CN=Users,DC=domain,DC=com" userObjectClass="person" userFilter="(|(ObjectCategory=group)(ObjectClass=person))" scope="Subtree" otherRequiredUserAttributes="sn,givenname,cn" connectionUsername="clientsdomain\administrator" connectionPassword="SDJFSew98234DFJ889==" />
<add name="EmployeesADMembershipProvider" type="Microsoft.Office.Server.Security.LDAPMembershipProvider, Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71E9BCE111E9429C" server="dc.employeesdomain.com" port="389" useSSL="false" userDNAttribute="distinguishedName" userNameAttribute="sAMAccountName" userContainer="CN=Users,DC=domain,DC=com" userObjectClass="person" userFilter="(|(ObjectCategory=group)(ObjectClass=person))" scope="Subtree" otherRequiredUserAttributes="sn,givenname,cn" connectionUsername="employeesdomain\administrator" connectionPassword="SL43Sew982342KLSDF==" />
<add name="CustomLdapProvider" type="Project.CustomLdapProvider, Project, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8027a17523a78ae328" />
</providers>
</membership>
The partial implementation of CustomLdapProvider will be something like below:
public class CustomLdapProvider : MembershipProvider
{
private static LdapMembershipProvider _employeesProvider = null;
private static LdapMembershipProvider _clientsProvider = null;
private LdapMembershipProvider GetMembershipProvider(string providerName)
{
LdapMembershipProvider provider = new LdapMembershipProvider();
// In SharePoint when your login page is coming from Layouts folder, HttpContext.Current is returning null. Hence the next line.
//Configuration config = WebConfigurationManager.OpenWebConfiguration(HttpContext.Current.Request.ApplicationPath);
Configuration config = WebConfigurationManager.OpenWebConfiguration(@"~/web.config");
MembershipSection section = (MembershipSection)config.GetSection("system.web/membership");
ProviderSettings providerSettings = section.Providers[providerName];
NameValueCollection param = providerSettings.Parameters;
param["connectionPassword"] = Utility.Decryption(param["connectionPassword"], true);
provider.Initialize(providerName, param);
return provider;
}
private MembershipProvider EmployeesProvider
{
get
{
if (_employeeProvider == null)
{
_employeeProvider = GetMembershipProvider("EmployeesADMembershipProvider");
}
return (MembershipProvider)_employeesProvider;
}
}
private MembershipProvider ClientsProvider
{
get
{
if (_clientsProvider== null)
{
_clientsProvider = GetMembershipProvider("ClientsADMembershipProvider");
}
return (MembershipProvider)_clientsProvider;
}
}
// Override all the membership provider and use the appropriate Membership provider to call the overloads.
public override bool ValidateUser(string name, string password)
{
// name = loginid@clientsdomain.com / loginid@employeesdomain.com
// Extract the domain name and based on the domain connect to the appropriate Membership Provider (EmployeesProvider, ClientsProvider) and call the ValidateUser.
// Ex: ClientsProvider.ValidateUser(name, password)
}
}
I am sure this will be quite useful in implementing Forms Based Authentication in SharePoint when you have to work against an LDAP Provider and do not want to compromise on the connection string.
Thursday, January 27, 2011
Programatically create Power Pivot Gallery
Have you ever tried creating Power Pivot Gallery?
It isn't straight forward.You cannot just use the
web. ListTemplates["ReportGalleryLibrary"]. I found that the ListTemplates had the required template but it wasn't accepting the Internal name of ReportGalleryLibrary.
The error I was getting was "Value does not fall within the expected range."
Here is the code to Create a Pivot Gallery on a given Web.
public void CreatePowerPivotGallery(SPWeb web, string galleryName, string description)
{
web.AllowUnsafeUpdates = true;
SPListTemplate template = null;
foreach (SPListTemplate temp in web.ListTemplates)
{
if (temp.InternalName == "ReportGalleryLibrary")
{
template = temp;
break;
}
}
if (template == null)
{
throw new Exception();
}
web.Lists.Add(galleryName, description, template);
web.Update();
web.AllowUnsafeUpdates = false;
}
{
web.AllowUnsafeUpdates = true;
SPListTemplate template = null;
foreach (SPListTemplate temp in web.ListTemplates)
{
if (temp.InternalName == "ReportGalleryLibrary")
{
template = temp;
break;
}
}
if (template == null)
{
throw new Exception();
}
web.Lists.Add(galleryName, description, template);
web.Update();
web.AllowUnsafeUpdates = false;
}
Usage:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(@"http://mymachine:30000/"))
{
using (SPWeb web = site.OpenWeb())
{
CreatePowerPivotGallery(web, "SomeNewGallery", "Power Pivot Gallery");
}
}
});
{
using (SPSite site = new SPSite(@"http://mymachine:30000/"))
{
using (SPWeb web = site.OpenWeb())
{
CreatePowerPivotGallery(web, "SomeNewGallery", "Power Pivot Gallery");
}
}
});
Note: Ensure that the Site Collection has the "PowerPivot Feature Integration for Site Collections" feature enabled.
Labels:
ListTemplate,
Power Pivot Gallery,
SharePoint 2010
Monday, January 24, 2011
Troubleshooting in SharePoint 2010 - ULS Logs : Correlation ID
I am sure all of you have worked with Logs to figure out what is happening within your SharePoint application. However, there are cases where you will need to know what is happening within the SharePoint services, that is causing a failure in your application. Especially when you see a message with a Correlation ID that is a pointer to SharePoint logs.
SharePoint 2010 provides interfaces to Read/Write into the common logging system.
You can configure what needs to be logged in the Central Administration > Monitoring > Reporting > Configure Diagnostics Logging.
Select the Service you are interested in with the required sub category and set the "least critical event to report to the trace log" to the level you intend to monitor. Medium would suffice in most of the case.
You can download a codeplex solution to make your life easier in reading these logs from
The Viewer is self explanatory, just load the log file from the LOGS folder of 14 hive and you are all good to go. I used the Notifications List & Filters very often to see a snap shot of the most critical errors.
Use the Toggle Correlation Tree icon on the top right to see a list of Correlation IDs.
Ctrl + Shift + I can be used for monitor a particular Correlation ID.
Good news is that SharePoint allows you to write your log messages into it's own framework so that you do not have to maintain two different logs one for your application and another for SharePoint.
Code to write to the SharePoint ULS Logs is as below:
public static void Write(string message)
{
SPDiagnosticsService logger = SPDiagnosticsService.Local;
logger.WriteTrace(0,
new SPDiagnosticsCategory("MyApp",
TraceSeverity.Monitorable,
EventSeverity.Error),
TraceSeverity.Monitorable,
"Application Message : {0}",
new object[] {message});
}
{
SPDiagnosticsService logger = SPDiagnosticsService.Local;
logger.WriteTrace(0,
new SPDiagnosticsCategory("MyApp",
TraceSeverity.Monitorable,
EventSeverity.Error),
TraceSeverity.Monitorable,
"Application Message : {0}",
new object[] {message});
}
That's it for now. Good luck on your next troubleshooting!
Saturday, January 8, 2011
Logging using Enterprise Library... How simple is that?
I am sure you will agree with me how much a logging class is useful to help you isolate that problem. Especially when you are going through a lot of workflows which to simulate and debug becomes a nightmare.
Every project will require some kind of logging either you just want to see if your calls are made as expected OR if you want to take special actions like sending a mail based on the criticality of the log entry.
How long do you think it is going to take to do the following:
Add a class LogginManager.cs
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Diagnostics;
public static class LoggingManager
{
public static void Write(string message, TraceEventType eventType)
{
if (Logger.IsLoggingEnabled())
{
LogEntry entry = new LogEntry
{
Message = message,
Severity = eventType
};
Logger.Write(entry);
}
}
}
Add the following libraries in GAC
Microsoft.Practices.Unity.dll
Microsoft.Practices.Unity.Interception.dll
Microsoft.Practices.ServiceLocation.dll
Microsoft.Practices.EnterpriseLibrary.Logging.dll
Microsoft.Practices.EnterpriseLibrary.Common.dll
Now start using Logging class,
LoggingHandler.Write(ex.Message, System.Diagnostics.TraceEventType.Critical);
There is a tool to configure your web/app.config. Follow these basic steps to get you going.
To configure:
1. Open the web.config/app.config from the Enterprise Library Configuration tool. There is also a Visual Studio Add-in to configure directly from Visual Studio.
2. Blocks > Add Logging Settings
3. Add a Logging Target Listener > Add Flat File Trace Listener – Change its formatter to Text Formatter.
4. Change the Listener for the General Category to Flat File Trace Listener
5. Change the Listener for the Logging Errors & Warnings to Flat File Trace Listener
6. Add a Logging Filter > Logging Enabled Filter. Set All Logging to true
7. Save and you are good to go.
You should be able to see the logs in a file called Trace.log under your bin directory. You can change what you see as part of the Logs by modifying the Text Formatter contents.
Recommend using this for logging, there are lot more to offer from the Enterprise Library. Go through,
http://entlib.codeplex.com/wikipage?title=EntLib5&referringTitle=Home
Every project will require some kind of logging either you just want to see if your calls are made as expected OR if you want to take special actions like sending a mail based on the criticality of the log entry.
How long do you think it is going to take to do the following:
Add a class LogginManager.cs
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Diagnostics;
public static class LoggingManager
{
public static void Write(string message, TraceEventType eventType)
{
if (Logger.IsLoggingEnabled())
{
LogEntry entry = new LogEntry
{
Message = message,
Severity = eventType
};
Logger.Write(entry);
}
}
}
Add the following libraries in GAC
Microsoft.Practices.Unity.dll
Microsoft.Practices.Unity.Interception.dll
Microsoft.Practices.ServiceLocation.dll
Microsoft.Practices.EnterpriseLibrary.Logging.dll
Microsoft.Practices.EnterpriseLibrary.Common.dll
Now start using Logging class,
LoggingHandler.Write(ex.Message, System.Diagnostics.TraceEventType.Critical);
There is a tool to configure your web/app.config. Follow these basic steps to get you going.
To configure:
1. Open the web.config/app.config from the Enterprise Library Configuration tool. There is also a Visual Studio Add-in to configure directly from Visual Studio.
2. Blocks > Add Logging Settings
3. Add a Logging Target Listener > Add Flat File Trace Listener – Change its formatter to Text Formatter.
4. Change the Listener for the General Category to Flat File Trace Listener
5. Change the Listener for the Logging Errors & Warnings to Flat File Trace Listener
6. Add a Logging Filter > Logging Enabled Filter. Set All Logging to true
7. Save and you are good to go.
You should be able to see the logs in a file called Trace.log under your bin directory. You can change what you see as part of the Logs by modifying the Text Formatter contents.
Recommend using this for logging, there are lot more to offer from the Enterprise Library. Go through,
http://entlib.codeplex.com/wikipage?title=EntLib5&referringTitle=Home
Subscribe to:
Posts (Atom)