Jan 12 2012

SharePoint 2007 Error: The type or namespace name 'Publishing' does not exist in the namespace 'Microsoft.SharePoint' (are you missing an assembly reference?)

Category: ASP.NET | SharePointDavid @ 19:06

If your looking for the solution to the above error in SharePoint due to the use of the SPUrlExpressionBuilder (SPUrl) you will want to try a couple of things. The first is to include the following page declarations in the MasterPage if you have not already. 

<%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" 
Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.Publishing.Navigation"
Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="PublishingVariations" TagName="VariationsLabelMenu"
src="~/_controltemplates/VariationsLabelMenu.ascx" %>
<%@ Register Tagprefix="PublishingConsole" TagName="Console" src="~/_controltemplates/PublishingConsole.ascx" %> <%@ Register TagPrefix="PublishingSiteAction" TagName="SiteActionMenu"
src="~/_controltemplates/PublishingActionMenu.ascx" %>

If you continue to get the above error you might be having the issue that I ran into where I was using the SPUrl inside of an ASP.NET User Control.  This has to do with the way that the User Control and MasterPage are parsed.  The User Control is parsed by ASP.NET first prior to the MasterPage.  This means that the declarations in the MasterPage are not present for the User Control.  The solution is to also include the above declarations in the markup for the User Control. Including the declarations in the User Control insures that the SPUrl tag prefix has been registered prior to the parsing of the expressions that use it.


    

Tags: ,

Sep 16 2010

Visual Studio 2010 Web.config Transform adds unwanted linebreaks and whitespace

Category: .NET | ASP.NET | Visual Studio 2010David @ 11:12

One of the cool features in Visual Studio 2010 in the new web.config transform functionality for “automagically” changing the values in your web.config file based on your deployment scenario.

I’ve been working with this new feature now for a bit and just ran into an issue that was completely unexpected.  In one of my web applications I have an application setting that hold a filepath.  When I moved to using the web.config transform I encountered a bug where extra linebreaks and whitespace gets inserted into the body of the Value node for a given application setting.

Here’s an example of what you might have in you web.config file to begin with:

   1: <configuration>
   2: ...
   3:     <applicationSettings>
   4:       <MyApp.Properties.Settings>
   5:         <setting name="LocalFilePath" serializeAs="String">
   6:           <value>C:\temp</value>
   7:         </setting>
   8:       </MyApp.Properties.Settings>
   9:     </applicationSettings>
  10: ...
  11: </configuration>

And lets say that you have the following in your Web.Release.config transform file.

   1: <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
   2:     <applicationSettings>
   3:       <MyApp.Properties.Settings>
   4:         <setting name="LocalFilePath" serializeAs="String" xdt:Transfrom="Replace" xdt:Locator="Match(name)">
   5:           <value>D:\MyAppWebRoot\Files</value>
   6:         </setting>
   7:       </MyApp.Properties.Settings>    
   8:     </applicationSettings>
   9: </configuration>

After you publish the site and examine the the changes to your web.config file you will discover it looks like this:

   1: <configuration>
   2: ...
   3:     <applicationSettings>
   4:       <MyApp.Properties.Settings>
   5:         <setting name="LocalFilePath" serializeAs="String">
   6:           <value>
   7:           D:\MyAppWebRoot\Files
   8:           </value>
   9:         </setting>
  10:       </MyApp.Properties.Settings>
  11:     </applicationSettings>
  12: ...
  13: </configuration>

The resulting extra linebreaks and whitespace will cause all kinds of problems in your code if you don’t modify your code to trim the value of the property.  So, what can we do to fix this problem?  Well, you have one of three options:

  1. Add “.Trim” to your code in every place you use an application settings of type string. (What the heck!  Who wants to do that!?!)
  2. Forget about using the config transform until SP1 is release with a fix and just do it all manually. (Uh…have I ever mentioned how much I don’t like doing that now?)
  3. Modify the “Settings” class that is auto generated so that it trims the value of any application setting of type string. (BINGO!  I’ll take option three please!)

So, if your like me and you want option three then here is the code in both C# and VB that will get you what you want.  All you really need to do is create a code file in your project and drop the appropriate code in it with the right namespace defined.

BTW,  if you want to vote to have this fixed then here is the issue on the Microsoft Connect website.

C#

namespace MyApp.Properties
{
    internal sealed partial class Settings
    {
        public override object this[string propertyName]
        {
            get
            {
                string value;
                if ((value = base[propertyName] as string) != null) { return value.Trim(); }
                
                return base[propertyName];
            }
            set { base[propertyName] = value; }
        }

    }
}

 

Visual Basic.NET

Namespace My
    Partial Friend NotInheritable Class MySettings

      Default Public Overrides Property Item(ByVal propertyName As String) As Object
         Get
            If MyBase.Item(propertyName) IsNot Nothing Then
               If TypeOf MyBase.Item(propertyName) Is System.String Then Return MyBase.Item(propertyName).ToString.Trim
            End If

            Return MyBase.Item(propertyName)
         End Get
         Set(ByVal value As Object)
            MyBase.Item(propertyName) = value
         End Set
      End Property

   End Class
End Namespace

Tags: , ,

Nov 16 2009

Got ViewState?

Category: .NET | ASP.NET | Best Practices | Tips & TricksDavid @ 10:58

A few months ago I wrote a couple of posts on Managing Session Variables in ASP.NET using a Proxy. Since then I have thought about the need to write a post addressing the use of the ViewState as well.  As with SessionState,  ViewState is essential just a Dictionary of String, Object pairs.  This means that at design time you have to do a fair amount of type casting to use the objects you store in ViewState in a strongly typed manner.  It also introduces many of the same issues as using the native SessionState, such as:

  • the inability to know where you are using a given ViewState variable in your code.
  • the potential for mistyping a ViewState key when putting an object in ViewState or retrieving.
  • the increase in code to check for null values returned from ViewState.

Each of these issues is a pain to deal with on their own, but when the issues are compounded over a complex page then it really can make for a bad experience when developing.  The solution to this problem that I propose is to use custom properties on the page to access the various objects that are stored in ViewState.  Below is an example of a code behind page that illustrates how to do this.  This example assumes you have a class Person that defines properties of FirstName, LastName and ID, as well as a web page with two textboxes and a button.

   1: Partial Public Class _Default
   2:    Inherits System.Web.UI.Page
   3:  
   4:  
   5: #Region " Fields "
   6:  
   7:    Private Const _personViewState As String = "MyPerson"
   8:    Public Const QueryStringParameterPersonID As String = "pid"
   9:  
  10: #End Region
  11:  
  12: #Region " Properties "
  13:  
  14:    Public Property Person() As Person
  15:       Get
  16:          If ViewState(_personViewState) Is Nothing Then ViewState(_personViewState) = New Person
  17:          Return CType(ViewState(_personViewState), Person)
  18:       End Get
  19:       Set(ByVal value As Person)
  20:          ViewState(_personViewState) = value
  21:       End Set
  22:    End Property
  23:  
  24: #End Region
  25:  
  26: #Region " Methods "
  27:  
  28:    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  29:       If Not String.IsNullOrEmpty(Page.Request.QueryString(QueryStringParameterPersonID)) Then
  30:          'Get your user from your datastore and populate the Person Property with the returned user.
  31:          Person = PersonDAO.GetPersonByID(CInt(Page.Request.QueryString(QueryStringParameterPersonID)))
  32:       End If
  33:  
  34:       FirstNameTextbox.Text = Person.FirstName
  35:       LastNameTextBox.Text = Person.LastName
  36:  
  37:    End Sub
  38:  
  39:    Protected Sub SaveButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles SaveButton.Click
  40:       Person.FirstName = FirstNameTextbox.Text.Trim
  41:       Person.LastName = LastNameTextBox.Text.Trim
  42:  
  43:       'Persist your Person to your datastore, etc.
  44:    End Sub
  45:  
  46: #End Region
  47:  
  48: End Class

In this example you can see how I have abstracted the access to my ViewState Person object into a property that always returns an instance of a Person. You can of course have this property return null (Nothing) if you need or prefer that for your own development.  Either way you are still eliminating the direct reference to the ViewState allowing you to program against a strongly typed object.  As I did in my SessionProxy posts, I am using a private constant to hold the string value of my key to eliminate the chance of mistyping this value when using it in multiple places.

Another technique that I would like to point out in this post is the use of public constants to represent the string value of the query parameter names for this page.  By exposing a constant representing this value I then make it possible for other developers to easily see the parameters that my page accepts.  If they utilize the constant it will also allow me to change the actual string value of my parameter name at any point in time without affecting the functionality of my page. (I realize this is a big “If” that is reliant on team standards.)

Tags: , , , , ,

Aug 5 2009

Managing Session Variables in ASP.NET using a Proxy – Part 2

Category: .NET | Architecture | ASP.NET | Best Practices | Tips & TricksDavid @ 15:54

In my last post I gave an example of using the Proxy Design Pattern to manage your ASP.NET Session.  In this post I wanted to refine that proxy class through some refactoring and add some additional functionality to it that remove Session variables and also allow us to use the proxy to clear or abandon the Session as a whole. We will also create a mechanism for grouping Session variables into related objects in the SessionProxy.

First I want to add a private property that will allow me to eliminate some of the verbosity in my code.  I’ll add a private static property that encapsulates the current HTTPSessionState object.  We can then use that property to refactor our other properties so they are more readable.

   1: private static HttpSessionState Session { get { return HttpContext.Current.Session; } }

Next we’ll add some code into our properties that will check for the value being set and remove the Session variable from the Session object if necessary.  As an example I’ll use a new Property of type String.

   1: public static String CategoryName
   2: {
   3:    get 
   4:    {
   5:       if (Session[CATEGORYNAME] == null) { return String.Empty; }
   6:       return (String)Session[CATEGORYNAME];
   7:    }
   8:  
   9:    set 
  10:    {
  11:       if (String.IsNullOrEmpty(value)) { Session.Remove(CATEGORYNAME); }
  12:       else { Session[CATEGORYNAME] = value; }
  13:    }
  14: }

Now I want to add a few methods to allow me to use the SessionProxy to Clear the current Session or Abandon it.

   1: #region Methods
   2:  
   3: public static void Clear() { Session.Clear(); }
   4:      
   5: public static void Abandon() { Session.Abandon(); }
   6:      
   7: #endregion

At this point I feel that I have a pretty good proxy class that allows me to leverage my ASP.NET Session in a strongly type manner and to easily see what I am storing in the Session and what their types are.

However, in using this solution in a production application I have found that my list of properties has grown longer than I would like. There were close to two dozen at last count and all the Session variables have not been migrated to use the proxy.  I found myself increasingly tired of seeing all those properties each time I accessed the class.  On top of that some of the names were getting rather long in an effort to give them meaningful names.  To resolve this I implemented several properties on the SessionProxy that were child proxy objects.  To make things a bit easier I created a base class called SessionProxyChildProxyBase.  Here’s the code in full for that base class.

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Web;
   5: using System.Web.SessionState;
   6:  
   7: public abstract class SessionProxyChildProxyBase
   8: {
   9:  
  10:   #region Properties
  11:  
  12:   protected HttpSessionState Session { get { return HttpContext.Current.Session; } }
  13:  
  14:   #endregion
  15:  
  16: }

You will note a few points on this class.  Unlike the SessionProxy class the SessionProxyChildProxyBase class is an abstract class.  We don’t want to allow others to implement this base class outside of our library so that the SessionProxy class now becomes a proxy for this class as well as for the ASP.NET Session.  It also contains a protected Session property that will facilitate a decrease in code verbosity.

Now we will leverage this base class and create derived classes that will contain related properties.  In your application you may provide a central location for entering search criteria but you pass those criteria via the Session to a page that actually displays the search results.  Let’s create a child proxy class to organize the various values being passed.

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Web;
   5:  
   6: public class SearchSessionProxy: SessionProxyChildProxyBase
   7: {
   8:  
   9:   #region Fields
  10:  
  11:   private const String SEARCHTEXT = "SearchText";
  12:   private const String SEARCHTYPENAME = "SearchTypeName";
  13:   
  14:   #endregion
  15:  
  16:   #region Properties 
  17:  
  18:   public String Text
  19:   {
  20:      get
  21:      {
  22:         if (Session[SEARCHTEXT] == null) { return String.Empty; }
  23:         return (String)Session[SEARCHTEXT];
  24:      }
  25:  
  26:      set
  27:      {
  28:         if (String.IsNullOrEmpty(value)) { Session.Remove(SEARCHTEXT); }
  29:         else { Session[SEARCHTEXT] = value; }
  30:      }
  31:   }
  32:  
  33:   public String TypeName
  34:   {
  35:      get
  36:      {
  37:         if (Session[SEARCHTYPENAME] == null) { return String.Empty; }
  38:         return (String)Session[SEARCHTYPENAME];
  39:      }
  40:  
  41:      set
  42:      {
  43:         if (String.IsNullOrEmpty(value)) { Session.Remove(SEARCHTYPENAME); }
  44:         else { Session[SEARCHTYPENAME] = value; }
  45:      }
  46:   }
  47:  
  48:   #endregion
  49:  
  50:   #region Constructors
  51:  
  52:   internal SearchSessionProxy() { }
  53:  
  54:   #endregion
  55:  
  56: }

Now we need to add some code to our SessionProxy class to leverage this new class.  The first task is to add a private static field of type SearchSessionProxy.

   1: #region Fields
   2:  
   3: private static SearchSessionProxy _searchProxy = new SearchSessionProxy();
   4:  
   5: #endregion

Next we will create the property to access the field.

   1: public static SearchSessionProxy Search { get { return _searchProxy; } }

And that’s it!  Now we call utilize our SessionProxy with our new child proxy classes for organization and grouping so that we can doing something like this in our web app code…

   1: public void DoSomething() 
   2: {
   3:  SessionProxy.Search.Text = "Search Text entered by user";
   4:  SessionProxy.Search.TypeName = "Product Search";
   5:  SessionProxy.ProductID = 0;
   6:  Response.Redirect("SearchResults.aspx");
   7: }

Tags: , , , ,