Kanithi's Professional Blog

May 12, 2010

How to hide Left Navigation Menu (Quick Launch) in SP

Filed under: MOSS 2007 — Veera Kanithi @ 1:42 pm

Quick Launch is rendered using a delegate control by SPContentSiteMap provider.

  1. One  way to remove the Quick Launch bar is to modify the Master Page to remove the delegate control
  2. Other way is to hide the Quick Launch in a Content Editor Web Part as follows.
    • Add Content Editor Web Part to a Web Part Zone
    • Select Edit – Modify Shared Web Part
    • Under Layout, check the Hidden option
    • Click the Source Editor button and add the following CSS
    • <style>
      .ms-navframe {
      display:none;
      }
      </style>

January 7, 2010

Custom web.config changes using generic SharePoint feature receiver

Filed under: MOSS 2007 — Veera Kanithi @ 10:29 pm

While I was looking for a general solution to edit Web.Config using a SharePoint feature, I found an excellent article from Ryan McIntyre about creating an external XML file with all the custom modifications and using a common feature receiver, it would take the changes from the external xml file and merge them in web.config using SPWebConfigModification object.

I am impressed with this approach, as this will eliminate frequent changes to the feature receiver class and avoid compilation and rebuilding WSP. Just change the XML file and re activate the feature, it’s that simple. Enough said, details including the feature receiver class is in his site below.

http://randomdust.com/blogs/ryan/archive/2008/03/22/featurereceiver-for-applying-custom-web-config-changes.aspx

But the code Ryan used for feature receiver class, works only for element modifications not for creating new sections. In my case I got to create a new section in the web.config file for example “connectionStrings”. After further exploring the code, he used EnsureChildNode modification type, this will be good only for modifications, if you want create new sections we must use EnsureSection. But EnsueSection has a disadvantage, we can’t remove the sections from web.config on de activating the feature. But I felt it is fine to leave an empty section in the web.config, it doesn’t harm. Following are my modifications (highlighted) to the feature receiver class that Ryan developed, to accommodate both sections and elements.

protected SPFeatureReceiverProperties _properties;

public override void FeatureActivated(SPFeatureReceiverProperties properties) {

string fileLoc = properties.Definition.RootDirectory + “\\WebConfigChanges.xml”;

//Check to see if a WebConfigChanges.xml file exists. If yes, we have work to do

if (System.IO.File.Exists(fileLoc))

{

//Grab the properties

_properties = properties;

this.ProcessChanges(fileLoc, false);

}

}

public override void FeatureDeactivating(SPFeatureReceiverProperties properties) {

string fileLoc = properties.Definition.RootDirectory + “\\WebConfigChanges.xml”;

//Check to see if a WebConfigChanges.xml file exists. If yes, we have work to do

if (System.IO.File.Exists(fileLoc))

{ //Grab the properties

_properties = properties;

this.ProcessChanges(fileLoc, true);

}

}

public override void FeatureInstalled(SPFeatureReceiverProperties properties) {

/* no op */

}

public override void FeatureUninstalling(SPFeatureReceiverProperties properties) {

/* no op */

}

private void ProcessChanges(string FileLocation, bool removeModification)

{

string xPathLocation;

string elementName;

string sectionName;

Dictionary<string, string> attributes = new Dictionary<string, string>();

using (XmlReader reader = XmlReader.Create(FileLocation))

{

//Loop through all of the changes

while(reader.ReadToFollowing(“WebConfigChange”))

{

//Clean out any attributes from past iterations

attributes.Clear();

xPathLocation = reader.GetAttribute(“XPathLocation”);

elementName = reader.GetAttribute(“ElementName”);

//Check if there is any new Section required

sectionName = reader.GetAttribute(“SectionName”);

elementName = reader.GetAttribute(“ElementName”);

//Make sure we have at least a path and element

if (xPathLocation == null || elementName == null || sectionName == null)

throw new Exception(“WebConfigChange missing required XPathLocation or ElementName or SectionName attributes”);

//Get the Attributes to apply

if (reader.ReadToDescendant(“Attribute”))

{

do

{

attributes.Add(reader.GetAttribute(“Name”), reader.GetAttribute(“Value”));

} while (reader.ReadToNextSibling(“Attribute”));

}

//Do the update

UpdateWebConfig(xPathLocation, elementName, sectionName, attributes, removeModification);

}

}

}

private void UpdateWebConfig(string XPathLocation, string ElementName, string SectionName,

Dictionary<string, string> Attributes, bool removeModification)

{

try

{

SPWebApplication webApp = null;

//Get the web app

//First check if it was deployed to a Site Collection

SPSiteCollection siteCol = _properties.Feature.Parent as SPSiteCollection;

if (siteCol == null)

{

//Check if it was deployed to a site

SPSite site = _properties.Feature.Parent as SPSite;

if (site == null)

{

//Check if it was deployed to a Site

SPWeb web = _properties.Feature.Parent as SPWeb;

if (web != null)

webApp = web.Site.WebApplication;

}

else

webApp = SPWebApplication.Lookup(new Uri(site.Url));

}

else

webApp = siteCol.WebApplication;

if (webApp != null)

{

SPWebConfigModification modification;

//If no section name

if (SectionName == null)

{

modification = new SPWebConfigModification(ElementName + CreateAttributeString(Attributes), XPathLocation);

modification.Owner = “Company.MOSS.FeatureReceiver”;

modification.Sequence = 0;

modification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;

modification.Value = string.Format(CultureInfo.InvariantCulture, CreateModificationValueString(ElementName, Attributes), CreateModificationValueArgs(Attributes));

}

else

{

modification = new SPWebConfigModification(SectionName, XPathLocation);

modification.Owner = ” Company.MOSS.FeatureReceiver”;

modification.Sequence = 0;

modification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureSection;

modification.Value = String.Format(“<{0}/>”, SectionName);

}

 

if (removeModification)

webApp.WebConfigModifications.Remove(modification);

else

webApp.WebConfigModifications.Add(modification);

webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();

}

else

throw new ApplicationException(“Could not locate a web application”);

}

catch (Exception ex)

{

System.Diagnostics.EventLog el = new System.Diagnostics.EventLog();

el.Source = “WebConfigFeature”;

el.WriteEntry(ex.Message);

}

}

/// <summary>

/// Accepts a dictionary object with all of the attributes for the web modification and

/// creates a string representing the attribute values which can be used when creating

/// the SPWebConfigModification object.

/// </summary>

/// <param name=”Attributes”></param>

/// <returns></returns>

private string CreateAttributeString(Dictionary<string, string> Attributes)

{

//Create a string that looks like this (no line breaks):

//[@Assembly=\”Company.Moss.Activities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9eed2245513232a4\”]

//[@Namespace=\”Company.Moss.Activities\”]

//[@TypeName=\”*\”][@Authorized=\”True\”]

string result = “”;

//Check if there are attributes

if (Attributes.Count > 0)

{

foreach (KeyValuePair<string, string> kvp in Attributes)

{

result += “[@” + kvp.Key + “=\”” + kvp.Value + “\”]”;

}

}

return result;

}

private string CreateModificationValueString(string ElementName, Dictionary<string, string> Attributes)

{

//Create a string that looks like this:

//”<authorizedType Assembly=\”{0}\” Namespace=\”{1}\” TypeName=\”{2}\” Authorized=\”{3}\”/>”

string result = “<” + ElementName;

//Check if there are attributes (Kind of silly if there aren’t!)

if (Attributes.Count > 0)

{

int i = 0;

foreach (string key in Attributes.Keys)

{

result += ” ” + key + “=\”{” + i.ToString() + “}\””;

i++;

}

}

result += ” />”;

return result;

}

private object[] CreateModificationValueArgs(Dictionary<string, string> Attributes)

{

//Create an object that looks like this:

//”Company.Moss.Activities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9eed2245513232a4″, “Company.Moss.Activities”, “*”, “True”

object[] result = new object[Attributes.Count];

int i = 0;

foreach(string value in Attributes.Values)

{

result[i] = value;

i++;

}

return result;

}

Here is the sample WebConfigChanges.xml file with connectionStrings section and other elements.

<?xml version=”1.0″ encoding=”utf-8″ ?>

<WebConfigChanges>

<WebConfigChange XPathLocation=”configuration” SectionName=”connectionStrings”>

</WebConfigChange>

<WebConfigChange XPathLocation=”configuration/connectionStrings” ElementName=”add”>

<Attributes>

<Attribute Name=”name” Value=”MOSSConnectionString” />

<Attribute Name=”connectionString” Value=”Data Source=XXX;Initial Catalog=XXX;User Id=XXX; Password=XXX” />

<Attribute Name=”providerName” Value=”System.Data.SqlClient” />

</Attributes>

</WebConfigChange>

<WebConfigChange XPathLocation=”configuration/system.web/httpHandlers” ElementName=”add”>

<Attributes>

<Attribute Name=”verb” Value=”*” />

<Attribute Name=”path” Value=”ChartImg.axd” />

<Attribute Name=”type” Value=”System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ />

</Attributes>

</WebConfigChange>

</WebConfigChanges>

Remember to place this file in the folder where elements.xml of the feature file is located under the 12 hive.

December 31, 2009

Custom .NET Application integration to SharePoint

Filed under: MOSS 2007 — Veera Kanithi @ 3:07 pm

My thoughts on several integration levels of a custom .NET application to SharePoint…

  • Integration Level 0 (No Integration)

Advantages

  • Simplest solution as there is no need to integrate with MOSS 2007 or deploy.
  • More reliable as there is no reliance on MOSS 2007 services.
  • Server requirements are reduced as SharePoint services are not running/not required.
  • Simpler development and deployment model and debugging.
  • Regular workstations can be used for development and Visual Studio 2008 is good for development and no add-ons or extensions required.
  • Can take advantage of third party tools such as DevExpress and Log4net with little or no setup changes.
  • Service account can be used for database access, no need to worry about Single Sign On.

Disadvantages

  • Limited integration with existing MOSS 2007 portals.
  • Another hosting environment to maintain.
  • Cannot take advantage of list data that is available in MOSS 2007.
  • MasterPages and Login pages with common user controls must be developed.
  • Cannot take advantage of SharePoint security model
  • Integrating to MOSS 2010 will be another complete effort.

  

  • Integration Level 1 (Using ASP.NET 3.5 hosted inside MOSS 2007 as Application Pages)

Advantages

  • Simpler development Model compared to higher levels of integration and debugging the Business objects and data objects is possible.
  • SharePoint is aware of the page – so the link is natively visible to portals (i.e. the link doesn’t need to be added to SharePoint)
  • Can take advantage of SharePoint master page, so the look and fell will be consistent across the organization. This will fasten the development process as there is no need for login and other user controls.
  • Application can be developed in regular ASP .NET fashion and integrated into MOSS 2007 as application pages, so regular ASP .NET debugging can be leveraged.
  • Single hosting environment and other Windows 2003 web servers can be taken off
  • Can take advantage of SharePoint’s security model such as User Profile.
  • Can take advantage of some of SharePoint’s features for future development.
  • Can take advantage of collaboration with some existing list data.
  • Don’t have to concentrate as much as for regular .NET apps regarding the AppScan vulnerabilities
  • Can take advantage of .Net 3.5 features such as ADO .NET entity framework and LINQ compared to higher levels of integration
  • Since each page is independent of other, MOSS 2010 migration will be easier compared to higher levels of integration.
  • Can take advantage of MOSS features in application enhancements.

Disadvantages

  • Dependency upon MOSS.
  • More powerful servers are required as there will be single hosting environment that process both regular SharePoint information and ASP .NET web application.
  • Initial setup of integrating ASP .NET web app into MOSS 2007 could be a night mare as there are some configuration changes, master file changes and some code changes to integrate the custom.master file.
  • May find some difficulties working with some third party controls such as Dev Express.
  • May find some challenges in using open source utilities such as Log4net and Microsoft Data Access Applications blocks as MOSS 2007 requires the signed assembly.
  • Changes in development and deployment process as there will be integration and that needs to be done on a web server which has SharePoint installed.
  • Verbose logging should be enabled in order to track down the errors in the integration part.
  • Double hop issue, must use local db account to access the DB or configure Single Sign On.
  • Cannot use proper identity impersonate with SharePoint security model.

  

  • Integration Level 2 (Using ASP.NET 3.5 and developing inside MOSS 2007)

Advantages

  • Single hosting environment.
  • Can take advantage of full SharePoint’s security model.
  • Can take advantage of SharePoint’s rich controls such as SPGridView, built-in web parts and Workflows.
  • Can integrate with existing list data if any.
  • Can take advantages of MOSS 2010 easy development framework such as BCS.

Disadvantages

  • Dependency upon MOSS 2007.
  • Site Pages render slower in MOSS 2007.
  • There is reliance on more components – so reliability of system is lower.
  • More powerful servers are required as there will be single hosting environment that process both regular SharePoint information and ASP .NET web application.
  • May find some difficulties working with some third party controls such as Dev Express.
  • May find some challenges in using open source utilities such as Log4net and Microsoft Data Access Applications blocks as MOSS 2007 requires the signed assembly.
  • Difficulty in troubleshooting. There are different log files to search for the error and it’s not clear where to look.
  • Development environment issues could arise as work stations do not have SharePoint libraries installed.
  • Reduced ability to use new .NET 3.5 features such as ADO .NET entity framework and LINQ.
  • Oracle client must be installed on the server in order to connect to Oracle db
  • More effort in migrating to MOSS 2010 compared to Integration Level 1.

  

  • Integration Level 3 (Deep Integration with MOSS 2007 using Lists , Business Data Catalog and Data Sources)

Advantages

  • Single hosting environment.
  • Can take full advantage of SharePoint’s security model.
  • Can take advantage of SharePoint’s rich controls such as SPGridView, built-in web parts and Workflows.
  • Can leverage current look and feel of SharePoint sites if they already exist.
  • Lists are easily customized by users.
  • Notifications when data changes.
  • Can take advantages of MOSS 2010 easy development framework such as BCS.

Disadvantages

  • Complete revamp of business process flow and this will require significant user education.
  • Dependency upon MOSS 2007.
  • Site Pages render slower in MOSS 2007.
  • There is reliance on more components – so reliability of system is lower.
  • More powerful web servers and SQL server required.
  • Difficulty in troubleshooting. There are different log files to search for the error and it’s not clear where to look.
  • Performance and scalability issues using Business Data Catalog to connect to external data sources.
  • Insane Development Requirements: You must have a Windows 2003/2008 Server as your Workstation; you really should be local Administrator on it.
  • More effort in migrating to MOSS 2010 compared to other Integration Levels. 

December 11, 2009

Use “Save As” any email attachment or Document to SharePoint List

Filed under: MOSS 2007 — Veera Kanithi @ 3:50 pm

Your best bet is to add the SharePoint library as a Network location in your Windows Explorer. In windows explorer, right click on Computer –> Add Network Connection –> Add custom location (use the SharePoint library url). This allows you to use “save as” from any of your desktop applications (including Outlook and browser) to select your SharePoint library as well as using “Attach File” in an Outlook email to select files from the SharePoint library. This would also eliminate the need to have SharePoint open.

Explorer view of the SharePoint Library

Filed under: MOSS 2007 — Veera Kanithi @ 3:49 pm

You can also use the explorer view of the SharePoint Library (Library Name–>Actions–>Windows Explorer View) to drag&drop/copy&paste email (or just the attachments) and files from Outlook and your desktop. You can also sync this library back to Oultook so you can browse it from Outlook. Or for sending out files, while in Explorer view, mouse right click on one or more files, select “Sent To..”–>Mail Recipient. It would be great if SharePoint had that option under it’s Send to, but that is a third party add-on right now.

Drag your Outlook file attachment directly into Sharepoint

Filed under: MOSS 2007 — Veera Kanithi @ 3:49 pm

Did you know that you can drag your Outlook file attachment directly into Sharepoint?

It is straightforward with a few exceptions. Here are the steps:

Open your SharePoint site
Select the Document Library to store the file
Select the “Explorer View” of the Document Library
Now open Outlook
Open the Email with the attachment
Resize Outlook so you can see the explorer view of the document library

Click on the attachment and drag to the folder area of the explorer view

The beauty of this is that the file never gets pulled out of Outlook onto a local drive/directory and is less likely to present a security risk.

How to use SharePoint Log Files

Filed under: MOSS 2007 — Veera Kanithi @ 3:15 pm
Purpose: SharePoint has a new logging architecture that gives you a much better way of determining issues with your SharePoint farm.
Result: Know how to find and read the SharePoint log files
Task 1 – Turn on verbose and information logging

  • Open the Central Administration Console
  • Click “Operations” tab
  • Under “Logging and Reporting”, click “Diagnostic Logging”

          

  • For “Select a category”, select “All”
  • Under “Least critical event to report to the event log”, select “Information”
  • Under “Least critical event to report to trace log”, select “Verbose”

            

  • Click “Ok”

Task 2 – Review the log file

  • Open the 12 hive Logs directory (C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\LOGS)
  • Find the newest log file and open it
  • Open Microsoft Excel 2007
  • Copy and paste the data from the log file into Excel
  • In the menu, click “Data”
  • In the ribbon, under the “Sort & Filter” jewel, click “Filter”

             

  • A majority of your errors will revolve around the w3wp processes, therefore in the second column (process), click the filter dropdown
  • Uncheck “Select All”
  • Check all the w3wp.exe processes

            

  • Click “Ok”
  • Review the entries that are present, when any exception occurs across SharePoint it will show up here!
Exercise #2 – Log to SharePoint Log File
Purpose: Learn to append your own messages to the log file
Result: Log entries in the Log files
Task 1 – Create a console application

  1. Open Visual Studio 2005
  2. Create a new console application
    • Click File->New->Project
    • Select Console Application
    • For location, type “D:\Lab Work”
    • For name, type “Logger”
    • Click Ok
  3. Add a reference to Microsoft.Office.Server.dll
    • Right click the project, select “Add Reference”
    • Click the Browse tab
    • Browse to c:\program files\common files\microsoft shared\web server extenstions\12\isapi
    • Select Microsoft.Office.Server.dll
    • Click Ok
  4. Update the Main code to the following:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Office.Server;
    namespace ConsoleApplication2
    {
    class Program
    {
    static void Main(string[] args)
    {
    try
    {
    throw new Exception(“Something bad happend”);
    }
    catch (Exception ex)
    {
    Microsoft.Office.Server.Diagnostics.PortalLog.LogString(“This was a bad one…”, null);
    }
    }
    }
    }
  5. Run the application
  6. Open the log files, find your log entry

            

Create a free website or blog at WordPress.com.