Prashant Nayak

Chit chat about SharePoint and .Net dev
Welcome to MSDN Blogs Sign in | Join | Help
SharePoint 2010 is finally here...

Lot of people waiting for final announcement for SharePoint vNEXT (2010) and it finally annouced today over at SPC 2009 in Las Vegas. Tons of content, great sessions, exciting new features for SharePoint 2010.

My top 5 favorite features:

1. Web 2.0 style UI

2. Metadata management across farms

3. Insight aka BI featuers (Performace Point services, Visio services, New Excel services, PowerPivot for Excel 2010 formerly Gemini etc)

4. BCS (Business Connectivity Services)

5. Developer Dashboard and Visual Studio 2010 support for SharePoint Development

For more info check out the link http://www.mssharepointconference.com/pages/default.aspx 

 

 

401 Unauthorized Error using WebRequest when accessing local SharePoint site

 

Colleague of mine asked me to research this issue and thought of sharing the solution as this is not clearly discussed anywhere on the Internet.

Problem:

Accessing local SharePoint site (with Windows Integrated Authentication) works fine using IE, however if the same site is accessed via .NET console application using HttpWebRequest object it throws 401 Unauthorized error.

Solution:

I tried bunch of things such as DefaultCredentials, NetWorkCredentials and ImpersonationTokenType etc but none would work. Apparently it was not a code but it was something very simple. Guess what! it has to do with custom host entry. Weird huh?

Here’s the KB article that resolved the issue (followed method 2 and restart the machine)

http://support.microsoft.com/default.aspx?scid=kb;en-us;896861

Details:

Usually SharePoint developers uses single VPC and create web application with URL entry like http://Litware and adds an entry of Litware in Host file to point back to 127.0.0.1. This works great for usual SharePoint development.

The IE works great as it automatically uses integrated authentication. However, for console application it doesn’t work when the Web site uses Integrated Authentication and has a name that is mapped to the local loopback address.

[Remark: This solution is only been tested on Windows 2003 R2, MOSS 2007 SP1 and December Cumulative Update, .Net 3.5 Sp1.]

SharePoint developer’s quick tips

This is mostly for my quick go to place to get some quick copy/paste when I am not around my machine!

How to extract Public key token using Visual Studio?

Add a custom tool in Visual Studio as

C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\Sn.exe -Tp $(TargetDir)$(TargetName)$(TargetExt)

(select Output window)

How to quickly get new GUID using Visual St

Add a custom tool as

C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools
SharePoint Schema Locations

Create CAML.XML file using notepad and add following code

   1:  <SchemaCatalog xmlns="http://schemas.microsoft.com/xsd/catalog"> 
   2:  <Schema href="C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\XML\wss.xsd" 
   3:  targetNamespace="http://schemas.microsoft.com/sharepoint/"/> 
   4:  </SchemaCatalog>

Drop this file to

%ProgramFiles%\Microsoft Visual Studio 8\Xml\Schemas\
Recycle app pools in IIS6

IIS6

%systemroot%\System32\iisapp.vbs /a "<app pool name>" /r

IIS7

%systemroot%\System32\inetsrv\APPCMD.exe recycle apppool "<App Pool Name>"
Quick MOSS Exception Logging (MOSS SDK says “Internal Use Only” – so be careful!)
   1:  catch(Exception Ex)
   2:   
   3:  {
   4:   
   5:  Microsoft.Office.Server.Diagnostics.PortalLog.LogString(”Exception Occurred: {0} ”, Ex.ToString());
   6:   
   7:  }

Nope! I am not taking any credit for it - collected it from various seasoned SharePointers!

Happy SharePointing!
Hide and automatically check [Sign me in automatically] check box in SharePoint FBA login page

Why to hide and check "Sign me in automatically" button?

Main reason is to facilitate smooth user experience, especially with respect to Microsoft Office Integration with SharePoint. This integration issue is extensively covered by Steve Peschka's MSDN article on FBA (Part 2 of 3).

Issue:
WhenWindows SharePoint Services web application is extended with FBA then the MS Office Integration isn't that smooth and there are some extra steps involved working with Office Documents such as Manually check-out, check-in, download temporarily to desktop then edit and upload etc.

Solution (or rather a workaround):
One of the work around to smoothen this experience is to check "Sign me in automatically" checkbox which sends the persistent cookie and thus Office programs works smoothly by using that cookie.

You might ask isn't that a risk to allow user to keep them signing in without their knowledge? Yes, but that's the trade-off. I am not saying compromise the security but its the happy middle ground for seamless user experience.

Steps to modify login.aspx page:

  1. Create a sub-directory (myApp) in 12 hive's layouts directory (C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\template\layouts)
  2. Copy login.aspx file to this sub-direcroty from parent directory (layouts directory) and rename it to myLogin.aspx.
  3. Modified myLogin.aspx page as shown further.
  4. Change web.config file of the FBA Web application to redirect login.aspx page to your custom page (/_layouts/myApp/myLogin.aspx) as shown below

    <
    authentication mode="Forms">
    <forms loginUrl="/_layouts/myApp/myLogin.aspx" />
    </authentication>

     

Modify myLogin.aspx page.
  • First hide the checkbox  by adding  style="display:none;" attribute to <td colSpan=2> tag which surrounds check box.
  • Replace <table class="ms-input"> tag with following:

    <table class="ms-input" onmousedown="javascript:for(var i=0;i<document.forms[0].elements.length;i++){if (document.forms[0].elements[i].type=='checkbox'){document.forms[0].elements[i].checked=true;break;}};" onkeypress="javascript:for(var i=0;i<document.forms[0].elements.length;i++){if (document.forms[0].elements[i].type=='checkbox'){document.forms[0].elements[i].checked=true;break;}}">
  • What's happening here?
    Yeah, I know its hard to read. All I am doing is trapping onmousedown and onkeypress event on main table tag which surrounds User Name and Password text boxes, so that anytime user either enters user name or password or even copy/paste (using mouse or CTRL+V) this is sure way to fire the script and then it automatically checks the check box.

    What's this in-line javascript doing?
    Instead of using hard-coded ID for the check-box , I am looping through the form elements and enabling first checkbox upon key press or mouse down. Of course, assuming that "sign me in automatically" check box is first in the form element (you may want to tweak if you have extensively customized this OTB form and created your own with multiple check-boxes)

     

     

    Why in-inline Javascript and why not simply add property Checked="true" in <asp:checkbox> control?
    Because Checked="true" doesn't work, as on form load checkbox gets initialized and by default its unchecked. Secondly, in line javascript is allowed in SharePoint pages, however <script> tag is restricted dues to security reasons.

    Hope this may save some hours for some of you. Just sharing the point for SharePoint :-)

    Announcing Microsoft SharePoint Administration Toolkit 1.0

    This toolkit help reduce some of the pains for SharePoint administrators, especially managing ever growing Site collections. It contains two important functionality:

    • Batch Site Manager, which can be used by an administrator to manage and administrate bulk operations for moving, deleting, and locking site collections within a SharePoint farm.
    • A new Stsadm command-line tool operation called updatealert that updates alert e-mails when the Uniform Resource Locator (URL) for a Web application is changed

    Whitepaper is available here. (Binaries are soon to be available...)

    Console app to start incremental crawl in MOSS 2007

    Wrote a little Console application to kick start incremental crawl in MOSS 2007.

    Here's how it can be used.

    Usage: StartIncrementalCrawl.exe SiteURL "Content SourceName"
    (Example: StartIncrementalCrawl.exe http://MyMOSSSite "Local Office Sharepoint Server Sites" )

    As you can see, First I am getting the [SearchContext] Reference and then [ContentSources] collection, then just search for the passed content source name string.  Upon finding the content source, kick the incremental crawl on [ContentSrouce] object with static method StartIncrementalCrawl().
    (Note: This utility should be run under the context of Farm Admin only)

    Copy paste following code in a console app.

    using System;

    using System.Collections;

    using System.Text;

    using Microsoft.Office.Server.Search.Administration;

    using Microsoft.SharePoint;

     

    namespace PN.Moss.Samples

    {

        /// <summary>

        /// Console app to start Incremental Crawl

        ///

        /// Usage: StartIncrementalCrawl.exe SiteUrl "ContentSourceName"

        /// (Example: StartIncrementalCrawl.exe http://MyMossSite "MyContentSource")

        ///

        /// </summary>

        class Program

        {

            static void Main(string[] args)

            {

                try

                {

                    if (args.Length < 2)

                    {

                        Usage();

                        return;

                    }

     

                    Console.WriteLine("Getting Search context...");

                    string strURL = args[0];

                    SearchContext context;

                    using (SPSite site = new SPSite(strURL))

                    {

                        context = SearchContext.GetContext(site);

                    }

                    Content sspContent = new Content(context);

                    string strContentSource = args[1];

     

                    Console.WriteLine(string.Format("Searching content source [{0}] ...", strContentSource));

     

                    ContentSourceCollection sspContentSources = sspContent.ContentSources;

                    if (!sspContentSources.Exists(strContentSource))

                    {

                        Console.WriteLine("====================================================================");

                        Console.WriteLine(string.Format("ERROR: Unable to find content source [{0}]. \nPlease provide correct content source name.", strContentSource));

                        Console.WriteLine("====================================================================");

                    }

                    else

                    {

                        ContentSource cs = sspContentSources[strContentSource];

                        if (cs.CrawlStatus == CrawlStatus.Idle)

                        {

                            Console.WriteLine("Starting Incremental Crawl...");

                            cs.StartIncrementalCrawl();

                            Console.WriteLine("====================================================================");

                            Console.WriteLine("Incremental Crawl started Successfully.\nPlease check SSP web site for completion.");

                            Console.WriteLine("====================================================================");

                        }

                        else

                        {

                            Console.WriteLine("====================================================================");

                            Console.WriteLine(string.Format("ERROR: Unable to start incremental crawl, as crawl status is not [idle].\n\n[INFO: Current Crawl Status={0}] \n\nPlease verify and try after crawl status becomes idle.", cs.CrawlStatus.ToString()));

                            Console.WriteLine("====================================================================");

                        }

                    }

                   

                }

                catch (Exception e)

                {

                    Console.WriteLine("=========================");

                    Console.WriteLine("*** Exception Occured ***");

                    Console.WriteLine("=========================");

                    Console.WriteLine(e.ToString());

                }

            }

            private static void Usage()

            {

                Console.WriteLine("=========================");

                Console.WriteLine("Start Incremental Crawl");

                Console.WriteLine("=========================");

                Console.WriteLine("Usage: StartIncrementalCrawl.exe SiteUrl \"ContentSourceName\"");

                Console.WriteLine("");

                Console.WriteLine("(Ex: StartIncrementalCrawl.exe http://MyMossSite \"MyContentSource\")");

            }

        }

    }

     

     

    HOWTO: Host Office Documents with VSTO automation inside SharePoint 2007 Document Library

    It’s very easy to upload Word template to Microsoft Office SharePoint (MOSS) 2007 document library. However, it’s not that straight forward to setup and deploy Word template with VSTO code behind in MOSS 2007 document Library.

    Following guidelines shows how to deploy such documents to a MOSS 2007 document library and make sure they work in as long as Users have access to Deployment Manifest.

    Prerequisites for Clients

    ·         The Microsoft .NET Framework version 2.0

    ·         Microsoft Office 2003 applications that support VSTO 2005 document-based solutions
    OR
    Microsoft Office 2003 applications that support VSTO 2005 SE add-ins

    ·         Primary Interop assemblies
    A typical installation of Microsoft Office 2003 or a stand-alone product such as Word sets the applications to install the primary interop assemblies on first use of the product. A full installation installs the primary interop assemblies during the installation process.
    If you do not know whether a specific computer has the Primary Interop Assemblies installed, you should install the primary interop assemblies as part of your solution.

    ·         VSTO 2005 SE runtime

    ·         Visual Studio Tools for Office Language Pack (optional)

    Steps for Building and Deploying VSTO solution:

    1. Create VSTO Project

    Create VSTO project for the Document level add-in for Word 2003/2007 using Visual Studio Tools for Office 2005 SE. Add necessary code to successfully run the project.

     

    2. Build and Publish the solution

    Once successfully built and tested, publish the project. Using Visual Studio 2005 publishing wizard, publish the project to network file share or SharePoint share.
    (Note: End user MUST have access to this location without getting prompted to Network Credentials. This is the location where Deployment Manifest and assemblies will be located.)

    3. Grant full trust to the network folder

    Before granting permission, first Add Msosec.dll to the global assembly cache (GAC). Msosec.dll is the assembly that implements Microsoft.Office.Security.Policy.OfficeDocumentMembershipCondition, which is used to identify documents and workbooks. You can find Msosec.dll in the ADDINS folder under your Office installation location, which by default is \Program Files\Microsoft Office\OFFICE11\ADDINS.

    How to Add MSOSEC.DLL to the assembly cache:

    GacUtil.exe is targeted for developers and therefore it’s not shipped as part of the .NET 2.0 framework. For production environment, MSDN documentation suggests to use Windows Installer.

     Follow steps for creating Setup or Installer project in VS 2005.

    1.       Create [Setup] project using Visual Studio 2005

    2.       Right Click Project and Select View/File System.

    3.       Right Click [File System On Target Machine] and Add Special Folder [Global Assembly Cache Folder]

    4.        Select [Global Assembly Cache Folder] and then Right-Click and add [Assembly] and select C:\Program Files\Microsoft Office\Office11\ADDINS\MSOSEC.DLL

    5.        Build the solution and this will create SETUP.EXE and XXXX.MSI (XXXXX = [Name of the project]).

    Grant full trust to the assemblies in each end user's security policy.

    There are basically 2 automated ways to do this.

    1)       Create simple Batch file as follows:
    Example:

    Cd %systemroot%\Microsoft.NET\Framework\v2.0.50727

    caspol -m -ag LocalIntranet_Zone -url \\ServerName\FolderName\* Nothing -n "My Data Folder" -d "Intermediate group for my documents"

    caspol -m -ag "My Data Folder" -custom "C:\Program Files\Microsoft Office\Office11\Addins\Msosec.xml" FullTrust -n "My Data Documents" -d "Grants FullTrust to all documents in my data folder"

    caspol -m -ag LocalIntranet_Zone -url \\DeployServer\ShareFolder\* FullTrust -n "Remote Deployment" -d "Deployment Walkthrough"

    http://msdn2.microsoft.com/en-us/library/13wcxx6y(VS.80).aspx

    OR

    2)       Create Deployment Package as follows:

    ·         Basically, create a trust manually on the one of the computer using .NET Framework 2.0, start the SDK Command Prompt and type MSCORCFG.MSC 

    ·          In the left pane, right-click the Runtime Security Policy node.

    ·         From the menu, choose Create Deployment Package.

    http://msdn2.microsoft.com/en-us/library/13wcxx6y(VS.80).aspx

    5.  Upload the document template

    Once all of the above steps are completed, upload the Word Template document to MOSS 2007 document library. That's It.

    Good luck!  

     

    How to quickly generate CRUD Stored Procedure in SQL 2005?

    Found a cool tool to quickly generate CRUD (CREATE, READ, UPDATE, DELETE) stored procedure. It seemlesly adds a Context menu inside SQL Server Management Studio.

    http://weblogs.sqlteam.com/mladenp/archive/2006/12/28/55599.aspx

    Geeky LIVE.COM galleries

     

    Last night I was playing with Live.com and found cool stuffs to add to my Live.com page (http://gallery.live.com/home.aspx).  

    How to use TSQL parameters to actually use it as an Identifier rather than the value?

    This morning, someone asked that he was having difficulty getting dynamic count on column when Column Name is passed as parameter. Ahha...! Looks like he ran into same issue, once I came across.

    Problem:
    How to get a dynamic count of a column by passing a Column Name as a parameter in TSQL?

    Example:
    SELECT COUNT(@ColumnName) FROM FOO

    The above statement fails, as the parameter is not actually used as an Identifier.

    Solution:
    In TSQL, there is built-in stored procedure sp_executesql. This helps execute TSQL at runtime. Following TSQL code sample shows how to build a dynamic SQL to use parameter as an identifier.

    Code Sample:



    CREATE
    PROCEDURE [dbo].[TestDynamicCount]

            @TableName NVarchar(128) = 'dbo.Authors',

            @ColName NVarchar(128) = 'Name',

            @retVal int = -1 OUTPUT  

    AS

     

    DECLARE @OriginalCnt int,

    @ParmDefinition nvarchar(200),

    @sSQL nvarchar(200)

     

    SET @ParmDefinition =N'@Cnt1_Out int OUT'

     

    SET @sSQL= N'SELECT @Cnt1_Out=count('+@ColName+') FROM ' +  @TableName ;

    EXEC sp_executesql @sSQL, @ParmDefinition, @OriginalCnt Out;

    print @OriginalCnt

    SET @retVal=@OriginalCnt


     

    How to execute

    USE
    [Pubs]

    GO

    DECLARE @retVal int

    EXEC   [dbo].[TestDynamicCount]

           @TableName = N'dbo.Authors',

           @ColumnName = N'dbo.Name',  

           @retVal = @retVal OUTPUT


    SELECT
    @retVal as N'@retVal'

    GO

    In above example, @ColName is used to create concatenated SQL string which is then passed to sp_executesql to dynamically build TSQL query. Also note that second parameter @ParmDefinition contains the definitions of all parameters that have been embedded in stmt.

    Cheers!


    Page view tracker