Search This Blog

Thursday, April 28, 2011

SharePoint 2010 Pricing



Since last two days I've been struggling to get a rough idea about SharePoint 2010 prices for different scenarios and couldn't find a single link from Microsoft where I can see the prices straight. So after lots of effort I gathered some information on the pricing model which might not be accurate as it's not from the Microsoft and might change in future.

SharePoint 2010 licensing overview without prices:

Windows Server 2008 Pricing:

SQL Server Pricing:


Product
Price
Note
SharePoint 2010 Foundation
Free Download
Should have proper Operating System Licenses. It only works with classic authentication {Active directory users}. No claims based authentication is supported { SSO and Forms Authentication}
Download Link :
SharePoint 2010 Server
$4,926

SharePoint 2010 Server Standard CAL
$95

SharePoint 2010 Server Enterprise CAL
$95 + $83
You have to purchase standard license for enterprise to work.
SharePoint Server 2010 -Internet Sites - Standard Edition
$11,793

SharePoint Server 2010 -Internet Sites - Enterprise Edition
$41,392

FAST Search Server
$22,113


SQL server 2008 R2 (with 5 user CAL)
$1718

Windows server 2008 R2 (With 5 user CAL)
$726

External connector (Per server)
$2200
 External connector is used when you need to give active directory user access to only SharePoint Server and not any other functionality in the domain. 
*Listed prices do not include any Software Assurance cost.


You can compare all the features from the link provided below:

Some more granular details can find here:

Looking for the online quotation... see the link below
http://www.microsoft.com/licensing/mla/default.aspx

Monday, April 25, 2011

Sharepoint 2007 performance tips: Part 1 : " Using PortalSiteMapProvider to retrieve list data"

One of the ways to improve performance in SharePoint 2007 while fetching data from a list is by using 'PortalSiteMapProvider'.

'PortalSiteMapProvider' provides an automatic caching infrastructure for retrieving list data. The 'GetCachedListItemsByQuery' method of PortalSiteMapProvider takes an SPQuery object as a parameter, and then checks its cache to determine whether the items already exist. If they do, the method returns the cached results. If not, it queries the list and stores the results in a cache. This approach works especially well when you are retrieving list data that does not change significantly overtime.It results in good performance.
 
Here's the code that illustrates the same:

       // Get the current SPWeb object.
SPWeb curWeb = SPControl.GetContextWeb(HttpContext.Current);

// Create the query.
SPQuery curQry = new SPQuery();
curQry.Query = "<Where><Eq><FieldRef Name='Registration_x0020_Type'/>
<Value Type='Text'>User</Value></Eq></Where>";

// Create an instance of PortalSiteMapProvider.
PortalSiteMapProvider ps = PortalSiteMapProvider.WebSiteMapProvider;
PortalWebSiteMapNode pNode = ps.FindSiteMapNode(curWeb.ServerRelativeUrl) as PortalWebSiteMapNode;

// Retrieve the items.

SiteMapNodeCollection pItems = ps.GetCachedListItemsByQuery(pNode, "MyListName", curQry, curWeb);

// Enumerate through all of the matches.
foreach (PortalListItemSiteMapNode pItem in pItems)
   {
   // Do something with each match.
   }


However,it needs to be used with caution,as it has some limitations too:

-When data sets change frequently, the class incurs the performance cost of continually writing to the cache in addition to the costs of reading from the database.

-The PortalSiteMapProvider class uses the site collection object cache to store data. This cache has a default size of 100 MB. You can increase the size of this cache for each site collection on the object cache settings page for the site collection. But this memory is taken from the shared memory available to the application pool and can therefore affect the performance of other applications.

-Another significant limitation is that you cannot use the PortalSiteMapProvider class in applications based on Windows Forms.

Optimizing XML Document Upload by ignoring DTD

Few days back, I was struggling to optimize a piece of code for loading an XML through stream. The default XmlDocument.Load() was taking much time to load a document stream which was not more than 100 KB. After investigating the XML file I found that the file was taking long to upload because of the DTD tags. Since I have to directly parse XML to retrieve content, I was looking for a fast performing solution.
I searched for the XmlDocument namespace to get some idea of how to remove this DTD from XML document and found that the XmlDocument class loads XML files via the Load or LoadXml methods, which all ultimately convert to an XmlTextReader before reading the XML. There's one exception to this rule, however, and that's the Load overload that accepts an XmlReader. More than this, it's the XmlReader, and not the XmlDocument that resolves DTD validation arguments. It does this by using the XmlResolver set in the XmlReaderSettings.XmlResolver property.
To solve this issue, I created an instance of XmlReaderSettings, and probhited DTD processing by setting ProhibitDtd = false. I also removed the ability for the XmlReader to resolve the address specified in the DOCTYPE element by setting XmlResolver = null.
After doing this, we can safely create an XmlReader, and pass the reader into the Load method of the XmlDocument, and the XmlDocument will load the specified XML file without validating the document.
//get the xml document as filestream
XmlDocument uploadedFileStream = fileUploadCtrl.PostedFile.InputStream;
                   
if (uploadedFileStream != null)
    {
      try
       {
          //code optimized; dtd ignored for faster processing
          objXmlReaderSettings = new XmlReaderSettings();
          objXmlReaderSettings.XmlResolver = null;
          objXmlReaderSettings.ProhibitDtd = false
          objXmlReader = XmlTextReader.Create(uploadedFileStream,   objXmlReaderSettings);
       
          uploadedFileXmlDoc = new XmlDocument();
          uploadedFileXmlDoc.Load(objXmlReader);
                           
        }
       catch (XmlException xmlParseEx)
         {
  //custom exception handling
         }
    }

Dynamically Creating Sharepoint Content Type

In a scenario where you need to create Content Type in bunch, there comes the role of Dynamic Content types.

The following code snippet helps you in creating content type dynamically.

Code:

using System;using Microsoft.SharePoint;
namespace DynamicContentTypeConsole{ class Program { static void Main(string[] args) { string siteURL = "URL of Site"; using (SPSite objSPSite = new SPSite(siteURL))
{
using (SPWeb objSPWeb = objSPSite.OpenWeb()) { SPContentType objSPContentType = new SPContentType(
objSPWeb.AvailableContentTypes["ParentContentType"],
objSPWeb.ContentTypes, "Dynamic Content Type");
// A Required Field // Create Site Column objSPWeb.Fields.Add("Dynamic Number Column", SPFieldType.Number, true);
SPFieldLink objSPFieldLink1 = new SPFieldLink(objSPWeb.Fields["Dynamic Number Column"]); objSPContentType.FieldLinks.Add(objSPFieldLink1);
// A required String Field // Create Site Column objSPWeb.Fields.Add("Dynamic String Column", SPFieldType.Text, true);
SPFieldLink objSPFieldLink2 = new SPFieldLink(objSPWeb.Fields["Dynamic String Column"]);
objSPContentType.FieldLinks.Add(objSPFieldLink2);
//A non-required Choice Field // Create Site Column objSPWeb.Fields.Add("Dynamic Choice Column", SPFieldType.Choice, false);
SPFieldChoice choicefield = (SPFieldChoice)objSPWeb.Fields["Dynamic Choice Column"];
// Add a group to the filed choicefield.Group = "Dynamic Group";
// Add choices choicefield.Choices.Add(string.Empty); choicefield.Choices.Add("Yes"); choicefield.Choices.Add("No");
// Set the default choice choicefield.DefaultValue = string.Empty; choicefield.Update();
SPFieldLink objSPFieldLink3 = new SPFieldLink(choicefield); objSPContentType.FieldLinks.Add(objSPFieldLink3);
objSPWeb.Fields.AddLookup("Dynamic Lookup Column", new Guid("GUIDofRemoteList"), false);
SPFieldLookup lookupfield = (SPFieldLookup)objSPWeb.Fields["Dynamic Lookup Column"];
// Set the remote field lookupfield.LookupField = "RemoteFieldName"; lookupfield.Update(); SPFieldLink objSPFieldLink4 = new SPFieldLink(lookupfield); objSPContentType.FieldLinks.Add(objSPFieldLink4);
objSPWeb.ContentTypes.Add(objSPContentType); objSPContentType.Update(); } } } }}

The code snippet is the Console Application, and is ready to use.

Problem with sharepoint inputformtextbox control with updatepanel

When using SharePoint:InputFormTextBox control in UpdatePanel I faced one issue. On my webpart part page I had one SharePoint:InputFormTextBox control with one asp:DropDown control with autopostback property true. On SelectedIndexChanged event of that dropdown, InputformTextBox control appears without toolbar. This behaviour was coming because the InputformTextBox is a TextArea control. It needs script to achieve the rich text box feature when loading the page and in update panel due to partial postback the script was not loading. To fix this issue we are required to load that script. I am giving you the steps to fix this issue:
Step 1: Put this script function in design code.
<script language="javascript" type="text/javascript">
function CreateRichEdit(elementid)
{
if (browseris.ie5up && browseris.win32 && !IsAccessibilityFeatureEnabled()){
g_aToolBarButtons = null;
g_fRTEFirstTimeGenerateCalled=true;
RTE_ConvertTextAreaToRichEdit(elementid, true, true, "", "1033", null, null, null, null, null,"FullHtml", "\u002f",null,null,null,null);
RTE_TextAreaWindow_OnLoad(elementid);
RTE_DocEditor_AdjustHeight(elementid);
RTE_DocEditor_AdjustWidth(elementid);
}
else{
document.write("&nbsp;<br><SPAN class=ms-formdescription><a href='javascript:HelpWindowKey(\"nsrichtext\")'>Click for help about adding basic HTML formatting.</a></SPAN>&nbsp;<br>");
};
}
</script>


Step 2: Put this code in code behind file

protected void Page_PreRender(object sender, EventArgs e)
{
ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "@@CreateRichEdit", "<script>CreateRichEdit('" + InputformTextbox.ClientID + "');</script>", false);
}

Thanks
Prabhat

Sunday, April 24, 2011

Programmatically change the Welcome / Default page of a Sharepoint Publishing Web

Sometimes we have a requirement like on feature activation or deactivation we have to change the Welcome Page(Default Page) of the publishing site.
Below is the code snippet with the help of which we can change the Welcome Page:
public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            using (SPSite objSiteProperty = (SPSite)properties.Feature.Parent)
            {
                using (SPWeb objSPWeb = objSiteProperty.OpenWeb())
                {
                    PublishingWeb objPublishingWeb = PublishingWeb.GetPublishingWeb(objSPWeb);
                    SPFile objHomePageFile = objSPWeb.GetFile("Pages/Test.aspx");
                    objPublishingWeb.DefaultPage = objHomePageFile;
                    objPublishingWeb.Update();
                }
            }
        }

And in the same way on Feature Deactivation we can change the Welcome Page again.

Monday, April 18, 2011

LINQ to SharePoint provider - Part 1

LINQ to SharePoint provider enables us to use Language Integrated Query (LINQ) queries in our Microsoft SharePoint Foundation solutions. Rocking features of this provider are, it enables changing data using optimistic concurrency, object change tracking and resolution of conflicts is also supported by LINQ to SharePoint. Here I am introducing a very simple usage of LINQ in sharepoint 2010. To use the attached code first of all create a list named "Customers" having columns "Name", "CustomerId", "City".

Download Code : http://www.min.us/mb2BFA1cb6oztV

Page Title disappears after Ajax Post back

The Problem:
SharePoint page titles disappears when Ajax postback, title turn to square icons instead of page title.

We are having custom form and are using ajax to save the postback but when page postback asysnc the page title turns to square.

Solution :

This was the line in master page after master page design:

<title id=”onetidTitle”>
<asp:ContentPlaceHolder id=”PlaceHolderPageTitle” runat=”server”/>
</title>


After figuring out i found that if i removed the space between the html tag then problem get resolved and title appears as it required.

The correct line of code is as follows :

<title id=”onetidTitle”><asp:ContentPlaceHolder id=”PlaceHolderPageTitle” runat=”server”/></title>

Sharepoint People Picker control issue:"The control is not available because you do not have the correct permissions"

This is an issue that we faced recently in one of our sites where in only the admin user could see the sharepoint people picker control added on the page.For all the other users, the control was not visible and kept on giving the error:

"The control is not available because you do not have the correct permissions".



From the error , it seemed obvious that it was a permission issue.
We checked the group for the non admin user, also checked the people picker which was set to choose from 'All Users'but it didn't help.

Eventually , the solution to this problem was found in the permission levels.The permission level assigned to the non admin user was 'Contribute'. While checking the permission level settings , we found that a permission 'Browse User information' had bot been given due to which the users with the 'Contribute' permission level were not able to see other users information and hence not able to see the people picker control.

The solution was to grant this permission to the 'contribute' permission level.



If you are using a specific group for your functionality then change the settings for that group and allow everyone to see the group 





Once this was done, the people picker was visible to all users.


Access denied while activating feature in Sharepoint 2010



In my recent project I encountered a problem with Feature activation. I had to deploy some web.config changes using the package and then needed to propagate those changes across all the WFE’s on the server.  So I thought of creating a “Web Application” scoped feature to propagate the changes. But I received “Access Denied” while activating the feature from SharePoint. However when I tried doing the same through command line, it worked. 

After doing some R&D on this, I discovered that in SharePoint 2010, a new security feature has been added to all objects inheriting from SPPersistedObject in the Microsoft.SharePoint.Administration namespace. This feature explicitly disallows modification of the above stated objects from content web applications. The error message thrown was also very misleading but after some more tracing through the code I found a property in SharePoint API which controls this behavior. The property is:

“Microsoft.SharePoint.Administration.SPWebService.ContentService.RemoteAdministratorAccessDenied”

You can write this to your custom feature before executing your custom code.

public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            try
            {
              if (SPWebService.ContentService.RemoteAdministratorAccessDenied == true)
                {
                    SPWebService.ContentService.RemoteAdministratorAccessDenied = false;
                    SPWebService.ContentService.Update(true);
                }

              // Your custom logic goes here

            }
            catch (Exception Ex)
            {
// In case of any exception, you can easily trace it in the System Event //viewer
System.Diagnostics.EventLog.WriteEntry("Your custom Message", Ex.StackTrace, System.Diagnostics.EventLogEntryType.Error);
            }
        }


I have also written a PowerShell script for the same. Copy the below code and paste the contents in Note pad and save it with extension as .ps1

function LoadSharePointPowerShellEnvironment
{
   write-host
   write-host "Setting up PowerShell environment for SharePoint..." -foregroundcolor Yellow
   write-host
   Add-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue
   write-host "SharePoint PowerShell Snapin loaded." -foregroundcolor Green
}

function SetRemoteAdministratorAccessDenied()
{
       # load sharepoint API libs
       [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") > $null
       [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Administration") > $null

  # First get the content web service
 $contentService = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
  # Now set the remote administration security to off
 $contentService.RemoteAdministratorAccessDenied = $false
  # Also update the web service
 $contentService.Update()
        
}


#
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#                          Configuring RemoteAdministratorAccessDenied
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#

write-host
LoadSharePointPowerShellEnvironment

SetRemoteAdministratorAccessDenied