svchost.exe (LocalSystemNetworkRestricted) 100% Hard Disk usage

Print Content | More

Today on of my Vista developing workstations suddenly became very slow, the CPU was almost free and its usage was around 3-5%, the Hard Drive instead was overloaded with work, with its activity at 100% all the time. Trying to do any operation on the system requested ages..like 1 or 2 min to open the start menu or display a window.

Restating the system didn’t helped much, so I started to investigate the problem; opening the task manager and then the resource monitor I found out that I have many processes called like svchost.exe (LocalSystemNetworkRestricted) that were reading every files on the system (even the file related to the games I play at night).

So I opened the services management console to find something that could be run using svchost, I looked at every service there and found out that the ‘SuperFetch’ service (‘Ottimizzazione avvio’ in my Italian OS) was launched with this command: svchost.exe -k LocalSystemNetworkRestricted.

I disabled the service and rebooted the machine (I had to perform an hard reset cause the system was still hung reading the files on the disk). After the restart the problem disappeared and the system is back to be responsive.

In the end, it must be a bug of some sort related to the SuperFetch service, cause it ran fine for months without causing any problem.



100, Hdd, Localsystemnetworkrestricted, Superfect, Svchost

5 comments

WSS / SharePoint: adding filtering capabilities to the CustomListViewWebPart (Current User Filter and others)

Print Content | More

Two of the biggest limitation of the standard ListViewWebPart is that it’s unable to filter the data using more than one single data provider and that it cannot use multiple values if the provider is capable of providing them (only the first value will be used). This is by design and you cannot avoid it in any way.

To solve both these problems we can take the code we already wrote for our CustomListViewWebPart (see: WSS/SharePoint: Create a Custom ListViewWebPart) and modify it a bit to add the following features:

  • The support for multiple data providers (using the standard SP selection dialog to wire-up the fields with the provider values).
  • The support for multiple values from a single provider.
  • The <where> cause of the filter will be an <or> concatenation of all the values from a single provider, and will be an <and> concatenation of the different providers filter; a pretty standard way to filter the data from a table.

Most of the code is very similar to the previous version, so I will not go through it; let’s see the key points:

Multiple Providers Support

To make this Web Part able to connect to more than one provider, using the standard interfaces provided by SharePoint, we need to create a method with the signature: public void methodname(IFilterValues filterValues) and marked with then ConnectionConsumer attribute that specifies AllowMultipleConnections=true.

Inside that method we call the IFilterValues.SetConsumerParameters function that - given a collection of ConsumerParameter object (that specify the name and the capabilities of the parameters) - displays the standard SharePoint interface that allows you to choose to which field wire-up the provider.

To allow you to filter on all the fields of the list we will build the parameters starting from the list you are displaying through the instance of the Web Part. Here’s the code snippet:

[ConnectionConsumer("Filters", "FiltersForConsumer", AllowsMultipleConnections=true)]
public void SetFilter(IFilterValues filterValues)
{
   if (filterValues != null)
   {
      // EnsureChildControls();
      filterValues.SetConsumerParameters(GetParameters());
 
      FilterProviders.Add(filterValues);
   }
}
 
/// <summary>
/// Build a parameter List to allow the filtering of the List on the values provided
/// by a series of filters.
/// </summary>
/// <returns></returns>
private ReadOnlyCollection<ConsumerParameter> GetParameters()
{
   List<ConsumerParameter> parameters = new List<ConsumerParameter>();
   // we get all the fields of the list we are displaying
   SPList list = SPContext.Current.Web.Lists[SourceList];
   // we build a parameter for any field of the list (similar to the standard ListViewWebPart)
   foreach (SPField item in list.Fields)
      parameters.Add(new ConsumerParameter(item.Title,
          ConsumerParameterCapabilities.SupportsMultipleValues |
          ConsumerParameterCapabilities.SupportsAllValue |
          ConsumerParameterCapabilities.SupportsEmptyValue |
          ConsumerParameterCapabilities.SupportsSingleValue));
 
   return new ReadOnlyCollection<ConsumerParameter>(parameters);
}

FilterProviders is a List<IFilterValues> that will contains the associations made by the user.

Filtering the data

If you review the code from my previous article you will remind that to render the data we used a new instance of an SPView build from the schema of the selected view, and then we altered its properties to apply a fixed filter specified by the user. Here we will do the same but we will build this CAML <where> clause based on the wiring of the providers and consumer specified by the user.

The code is pretty straightforward and doesn’t need much comment, the ‘hardest’ part was to figure out how the CAML to write. Here’s the snippet:

   1: /// <summary>
   2: /// how to concatenate different filters
   3: /// </summary>
   4: const string FiltersConcatenation = "And";
   5: /// <summary>
   6: /// how to concatenate multiple values in the same filter
   7: /// </summary>
   8: const string FiltersMultipleValuesConcatenation = "Or";
   9:  
  10: private void BuildFilter(SPList list, SPView view)
  11: {
  12:    if (FilterProviders.Count == 0)
  13:       view.Query = FilterQuery;
  14:    else
  15:    {
  16:       if (FilterProviders.Count > 0)
  17:       {
  18:          // build the filter according to the passed data
  19:  
  20:          // holds each internal filter
  21:          List<string> filters = new List<string>();
  22:  
  23:          ReadOnlyCollection<string> paramValues;
  24:          foreach (IFilterValues f in FilterProviders)
  25:          {
  26:             paramValues = f.ParameterValues;
  27:  
  28:             if ((paramValues != null) && (paramValues.Count > 0))
  29:             {
  30:                StringBuilder innerSb = new StringBuilder();
  31:                if (paramValues.Count > 1)
  32:                   innerSb.AppendFormat("<{0}>", FiltersMultipleValuesConcatenation);
  33:  
  34:                foreach (var value in paramValues)
  35:                {
  36:                   innerSb.AppendFormat("<Eq><FieldRef Name='{0}' /><Value Type='{1}'>{2}</Value></Eq>", 
  37:                                        list.Fields[f.ParameterName].InternalName,
  38:                                        list.Fields[f.ParameterName].TypeAsString,
  39:                                        value);
  40:                }
  41:                if (paramValues.Count > 1)
  42:                   innerSb.AppendFormat("</{0}>", FiltersMultipleValuesConcatenation);
  43:  
  44:                filters.Add(innerSb.ToString());
  45:             }
  46:          }
  47:          if (filters.Count > 0)
  48:          {
  49:             StringBuilder sb = new StringBuilder();
  50:             sb.Append("<Where>");
  51:  
  52:             if (filters.Count > 1)
  53:                sb.AppendFormat("<{0}>", FiltersConcatenation);
  54:  
  55:             // concatenate the filters
  56:             filters.ForEach(f => sb.Append(f));
  57:  
  58:             if (filters.Count > 1)
  59:                sb.AppendFormat("</{0}>", FiltersConcatenation);
  60:  
  61:             sb.Append("</Where>");
  62:             string query = sb.ToString();
  63:             view.Query = query;
  64:          }
  65:       }
  66:    }
  67: }

As a note: if you keep adding and removing fields to a list in SharePoint you never know how the environment internally renames the fields (it happened to me once that a field with an internal name ‘Owner’ got renamed to ‘Owner1’), and you have no notice about it. The queries however need to be built using the Internal Names of the fields (that are different from those you usually see on the interface, there are lots of books and documentation around that cover this argument), so I opted to store the Display Name as the parameter name and to use that as a lookup field to recover the internal name (and type) when needed - lines 36-38 of the previous code snippet.

Putting all together

After some more refactoring operation, here is the complete source code for the Web Part:

[Guid("b7ea3f7d-b260-4ce8-9fd0-3af5aee8e0d6")]
public class CustomListViewWebPart : System.Web.UI.WebControls.WebParts.WebPart
{
   #region Properties
 
   private readonly ILogger Logger = LoggerFactory.GetLogger();
 
   /// <summary>
   /// The List we are displaying
   /// </summary>
   [Personalizable(true),
   WebBrowsable,
   WebPartStorage(Storage.Shared),
   SPWebCategoryName("Settings"),
   WebDisplayName("Source List Name"),
   WebDescription("Pass the name of the List to show")]
   public string SourceList { get; set; }
 
   /// <summary>
   /// The Default View of the list
   /// </summary>
   [Personalizable(true),
   WebBrowsable,
   WebPartStorage(Storage.Shared),
   SPWebCategoryName("Settings"),
   WebDisplayName("View"),
   WebDescription("Pass the name of the View that you want to apply to the List")]
   public string ViewOfSourceList { get; set; }
 
   /// <summary>
   /// a CAML query to filter the object
   /// </summary>
   /// <remarks>
   /// in a later revision we will use one or more filter providers to set this
   /// </remarks>
   [Personalizable(true),
   WebBrowsable,
   WebPartStorage(Storage.Shared),
   SPWebCategoryName("Settings"),
   WebDisplayName("Query"),
   WebDescription("Pass the Filter Query, if you wire up some Filter WebParts they have priority over the query and this will be ignored")]
   public string FilterQuery { get; set; }
 
   private readonly List<IFilterValues> _filterProviders = new List<IFilterValues>();
 
   private List<IFilterValues> FilterProviders
   {
      get { return _filterProviders; }
   }
 
   #endregion
 
   public CustomListViewWebPart()
   {
      ExportMode = WebPartExportMode.All;
   }
 
   protected override void CreateChildControls()
   {
      base.CreateChildControls();
 
      SPWeb web = SPContext.Current.Web;
      {
         try
         {
            SPList list = web.Lists[SourceList];
 
            // create the toolbar, actually we cannot hide it, we'll need to extend the webpart and those options
            ViewToolBar toolbar = new ViewToolBar();
            SPContext context = SPContext.GetContext(Context, list.Views[ViewOfSourceList].ID, list.ID, SPContext.Current.Web);
            toolbar.RenderContext = context;
            Controls.Add(toolbar);
 
            // get a reference to the view we want to use (or use the default view if nothing is specified)
            SPView webPartView;
            if (!string.IsNullOrEmpty(ViewOfSourceList))
               webPartView = web.Lists[SourceList].Views[ViewOfSourceList];
            else
               webPartView = web.Lists[SourceList].DefaultView;
 
            // create a new view based on the original one and attach the filter query to it
            // in this way we do not need to modify/update the original element and
            // even a user without updating permissions can use this webpart
            XmlDocument domDoc = new XmlDocument();
            domDoc.LoadXml(webPartView.SchemaXml);
            SPView view = new SPView(list, domDoc);
            Logger.AppendLogFormat("View ID: {0}", view.ID);
 
            // build the filter
            BuildFilter(list, view);
 
            // render the view
            Literal lbl = new Literal();
            lbl.Text = view.RenderAsHtml();
            Controls.Add(lbl);
 
            // add the logging messages if there are any
            string lg = Logger.ToString();
            if (!string.IsNullOrEmpty(lg))
            {
               Literal logLbl = new Literal();
               logLbl.Text = "<br/>" + lg;
               Controls.Add(logLbl);
            }
         }
         catch (Exception ex)
         {
            // todo: have a better way to report errors!
            Label lbl = new Label();
            lbl.Text = Logger.ToString() + "<br />";
            lbl.Text += "Error occured: ";
            lbl.Text += ex.Message + "<br />" + ex.StackTrace;
            Controls.Add(lbl);
         }
      }
   }
 
   /// <summary>
   /// how to concatenate different filters
   /// </summary>
   const string FiltersConcatenation = "And";
   /// <summary>
   /// how to concatenate multiple values in the same filter
   /// </summary>
   const string FiltersMultipleValuesConcatenation = "Or";
 
   private void BuildFilter(SPList list, SPView view)
   {
      Logger.AppendLogFormat("Filters numbers: {0}", FilterProviders.Count);
      if (FilterProviders.Count == 0)
         view.Query = FilterQuery;
      else
      {
         if (FilterProviders.Count > 0)
         {
            // build the filter according to the passed data
 
            // holds each internal filter
            List<string> filters = new List<string>();
 
            ReadOnlyCollection<string> paramValues;
            foreach (IFilterValues f in FilterProviders)
            {
               paramValues = f.ParameterValues;
 
               Logger.AppendLogFormat("Filter: {0}", f.ParameterName);
               Logger.AppendLogFormat("Filter Params: {0}", (paramValues != null));
 
               if ((paramValues != null) && (paramValues.Count > 0))
               {
                  Logger.AppendLogFormat("Found filter: {0}  values n: {1}", f.ParameterName, paramValues.Count);
 
                  StringBuilder innerSb = new StringBuilder();
                  if (paramValues.Count > 1)
                     innerSb.AppendFormat("<{0}>", FiltersMultipleValuesConcatenation);
 
                  foreach (var value in paramValues)
                  {
                     innerSb.AppendFormat("<Eq><FieldRef Name='{0}' /><Value Type='{1}'>{2}</Value></Eq>", 
                                          list.Fields[f.ParameterName].InternalName,
                                          list.Fields[f.ParameterName].TypeAsString,
                                          value);
                  }
                  if (paramValues.Count > 1)
                     innerSb.AppendFormat("</{0}>", FiltersMultipleValuesConcatenation);
 
                  filters.Add(innerSb.ToString());
               }
            }
            if (filters.Count > 0)
            {
               StringBuilder sb = new StringBuilder();
               sb.Append("<Where>");
 
               if (filters.Count > 1)
                  sb.AppendFormat("<{0}>", FiltersConcatenation);
 
               // concatenate the filters
               filters.ForEach(f => sb.Append(f));
 
               if (filters.Count > 1)
                  sb.AppendFormat("</{0}>", FiltersConcatenation);
 
               sb.Append("</Where>");
               string query = sb.ToString();
               view.Query = query;
               Logger.AppendLog("query: {0}" + query);
            }
            Logger.AppendLog("query: -");
         }
      }
   }
 
   protected override void Render(HtmlTextWriter writer)
   {
      EnsureChildControls();
      base.Render(writer);
   }
 
   [ConnectionConsumer("Filters", "FiltersForConsumer", AllowsMultipleConnections=true)]
   public void SetFilter(IFilterValues filterValues)
   {
      if (filterValues != null)
      {
         // EnsureChildControls();
         Logger.AppendLog("Assigning filters");
         Logger.AppendLogFormat("Assigning filter: {0}", filterValues.ParameterName);
         Logger.AppendLogFormat("Assigning filter: {0}", (filterValues.ParameterValues != null));
         
         filterValues.SetConsumerParameters(GetParameters());
 
         FilterProviders.Add(filterValues);
 
         Logger.AppendLog("Filters Assigned");
      }
   }
 
   /// <summary>
   /// Build a parameter List to allow the filtering of the List on the values provided
   /// by a series of filters.
   /// </summary>
   /// <returns></returns>
   private ReadOnlyCollection<ConsumerParameter> GetParameters()
   {
      List<ConsumerParameter> parameters = new List<ConsumerParameter>();
      // we get all the fields of the list we are displaying
      SPList list = SPContext.Current.Web.Lists[SourceList];
      // we build a parameter for any field of the list (similar to the standard ListViewWebPart)
      foreach (SPField item in list.Fields)
         parameters.Add(new ConsumerParameter(item.Title,
             ConsumerParameterCapabilities.SupportsMultipleValues |
             ConsumerParameterCapabilities.SupportsAllValue |
             ConsumerParameterCapabilities.SupportsEmptyValue |
             ConsumerParameterCapabilities.SupportsSingleValue));
 
      return new ReadOnlyCollection<ConsumerParameter>(parameters);
   }
 
}

This time I was lazy and I didn’t stripped out the logging code (I’m not particularly proud of that...but solved some logging problems fast).

You can see this Web Part in action in the following screenshots, here I defined a Document Library with a field called ‘Owner’ of type ‘Person or Group’, I dropped this CustomListViewWebPart together with the CurrentUserAndGroupsFilerWebPart from my previous article:

SharePointCLVWB1 SharePointCLVWB2_wp_config

When you drop the Web Part you have to configure some of its basic settings, like:

  • The List that it has to display
  • The View associated to the list to use (optional, if you leave this blank the default view will be used)
  • A custom query (optional, also if you specify some data providers this will be ignored).

And this is the interface you see when wiring the provider and the consumer:

SharePointCLVWB2_config

As you can see the appearance is almost identical to the standard Web Part, but you can filter on more providers and values (as a bonus you have the standard pagination capability too, cause it’s exposed by the view you decided to use).

Using these two simple Web Part we are able to achieve something that is extremely difficult to perform in WSS: filtering the data based on the User currently logged on the website (and I think that this approach is also easier that using the Target Audience in MOSS).

Further improvement to this Web Part will be made in the near future, because I’m hoping to introduce the ability to ‘plug-in’ even the algorithm that builds the actual filter combination; so stay tuned for more.



Sharepointwsscustomcurrent userfilterlistviewwebpart, Wss

10 comments

WSS/SharePoint: create a Current User Filter Web Part

Print Content | More

In MOSS we can filter some data on the currently logged User using the ‘Current User Filter Web Part’, unfortunately it’s not available in WSS. However building a simple Web Part that retriever the current user and that can be employed as a connection provider for other Web Parts isn’t that difficult.

To create a Web Part that act a data provider using the standard WSS/SharePoint infrastructure all you have to do is to implement the ITransformableFilterValues interface. You can then specify if your Web Part will provide single or multiple values for the parameter it will expose, if it can support an empty value and so on.

Accessing the currently logged user is extremely simple, actually it’s just a single line of code:

SPUser user = SPContext.Current.Web.CurrentUser;

We cannot return a plain SPUser object as the values of our provider Web Part, because the ITransformableFilterValues.ParameterValues that is actually used to return values to the callers is of type ReadOnlyCollection<string>.

So we have to find a way to return a single property and convert it to a string that is usable by the consumer; for this first barbaric implementation we simply define an enumeration that will state which field to extract and send to the consumer.

public enum ReturnType
{
   Name,
   ID
}

As an added feature we want to be able to filter on the currently logged and on the groups he belongs to (a thing that isn’t easily done using the standard WebParts that WSS offers); so our Web Part will return multiple values for it’s ‘CurrentUser’ parameter, the first value will always be the username or the user id, followed by the names or ids of the groups to which he belongs to.

Returning the user data as first parameter guarantees that you can use this filter provider with the standard ListViewWebPart (or other Web Parts) that WSS provides.

Here’s the actual implementation code:

[Guid("bf1f0d2a-eb32-4cbf-a3a0-561ae42bdf96")]
public class CurrentUserAndGroupsFilterWebPart : wsswebparts.WebPart, wsswebparts.ITransformableFilterValues
{
   public CurrentUserAndGroupsFilterWebPart()
   {
      ReturnType = ReturnType.Name;
   }
 
   /// <summary>
   /// The Default View of the list
   /// </summary>
   [Personalizable(true),
    WebBrowsable(),
    WebPartStorage(Storage.Shared),
    SPWebCategoryName("Settings"),
    WebDisplayName("Return Type"),
    WebDescription("Select if use the Name or the ID as the values retuned to the consumers")]
   public ReturnType ReturnType { get; set; }
 
   // Implementations of the ITransformableFilterValues properties.
   [wsswebparts.WebPartStorage(wsswebparts.Storage.None)]
   public virtual bool AllowMultipleValues
   {
      get
      {
         return true;
      }
   }
 
   [wsswebparts.WebPartStorage(wsswebparts.Storage.None)]
   public virtual bool AllowAllValue
   {
      get
      {
         return true;
      }
   }
 
   [wsswebparts.WebPartStorage(wsswebparts.Storage.None)]
   public virtual bool AllowEmptyValue
   {
      get
      {
         return false;
      }
   }
 
   [wsswebparts.WebPartStorage(wsswebparts.Storage.None)]
   public virtual string ParameterName
   {
      get
      {
         return "CurrentUser";
      }
   }
 
   [wsswebparts.WebPartStorage(wsswebparts.Storage.None)]
   public virtual ReadOnlyCollection<string> ParameterValues
   {
      get
      {
         List<string> data = new List<string>();
 
         // you have to filter on the same value that is displayed.
         SPUser user = SPContext.Current.Web.CurrentUser;
         // string strUser = "<Value Type='User'>" + user.ID + ";#" + user.LoginName + "</value>";
         if (user.IsSiteAdmin)
         {
            return null;
         }
 
         data.Add(ExtractData(user, this.ReturnType));
         foreach (SPGroup g in user.Groups)
         {
            data.Add(ExtractData(g, this.ReturnType));
         }
 
         return new ReadOnlyCollection<string>(data);
      }
   }
 
   private string ExtractData(SPPrincipal principal, ReturnType rt)
   {
      switch (rt)
      {
         case ReturnType.ID:
            return principal.ID.ToString();
         default:
            return principal.Name;
      }
   }
 
   // Use the ConnectionProvider attribute to specify the method that the Web Part
   // Framework should call to allow us to return an instance of our ITransformableFilterValues interface.
   [aspnetwebparts.ConnectionProvider("Current User And Groups", "CurrentUserAnGroupsID", AllowsMultipleConnections = true)]
   public wsswebparts.ITransformableFilterValues SetConnectionInterface()
   {
      return this;
   }
}

To use this Web Part just instantiate it on a page with a ListViewWebPart (the standard control that renders a document library is a ListViewWebPart), define a view on the list that will expose some data related to a user (it can be the standard Author field or a custom ‘User or Group’ field), wire up the two and you have your list filtered on the currently logged user.

Beware that the data returned by the filter Web Part and the data exposed by the view must match...so if you expose the ID, select the ID as the returned type of the filter.

In a next post I will show how you can modify the CustomListViewWebPart I presented earlier (Create a Custom ListViewWebPart) and allow it to become a multiple filters consumer (supporting multiple values for filters too), a thing that I wasn’t able to obtain using the standard Web Parts in WSS or MOSS.



Sharepointwsscustomcurrent userfilter

5 comments

VSeWSS: Unable to start debugging.The web server is not configured correctly

Print Content | More

If you ever tried to debug a SharePoint WebPart project created with VSeWSS, you might have faced this problem, and like me you might have lost a lot of time trying to check the IIS configuration following one of the many guides you can find around.

Here are some links:

http://msdn.microsoft.com/en-us/library/aa290100%28VS.71%29.aspx

http://msdn.microsoft.com/en-us/library/0y3b8byc.aspx

The error reported is quite misleading and the solution was extremely simple (and stupid): before following all the steps reported in the guides, check the web.config of the WSS/SharePoint site you are trying to debug and change the ‘debug=”false”’ line to ‘debug=”true”’; here’s how it should look like:

<compilation batch="false" debug="true">

I have to admit I’ve lost over 1 hour of my time on this...and I’m a bit upset :D



Sharepointwssvsewssunable to start debugging

0 comments

WSS/SharePoint: Create a Custom ListViewWebPart

Print Content | More

The standard ListViewWebPart, while it does a lot of work under the hood, offers quite limited functionalities when it comes to programmatically filter the data: even if you can wire up a filter WebPart that provide multiple values, only the first one will be considered; plus you can set only a single WebPart as the ‘data provider’ for the ListView (and this makes the realization of complex filter very hard).

You can rely on different techniques to accomplish the job:

- using SharePoint designer and create custom pages there (but it’s like hard coding the things and the reusability is minimal).

- you can define a set of views and assign them to different users, but it can be easily done only in MOSS using the Target Audience feature, and you cannot do it in WSS.

- other alternatives I do not know...

I didn’t liked any of these approaches and so I decided to try to customize the ListViewWebPart. You cannot directly inherit from the control (the class itself is marked as ‘sealed’, plus it can use many external resources you never know where they can reside given the structure of SharePoint).

I started the thing trying to use the original control, but there were problems in the way it handled the views..that is to work correctly it needs to refer to an existing view in the database; but in order to apply a custom filter query to that view, you have to call for the ‘Update’ method of the view object. If the user do not have the right permission that operation will fail and you’ll have an ‘access denied, log with another user’ (or something similar) error.

To overcome this I decided to create a brand new View object based on the schema of the current view (or the view the user have selected) and to call its RenderAsHtml() method; the result is a WebPart that act as the original ListViewWebPart, but that you can easily filter and customize (even in WSS).

Here’s the code:

[Guid("b7ea3f7d-b260-4ce8-9fd0-3af5aee8e0d6")]
public class CustomListViewWebPart : System.Web.UI.WebControls.WebParts.WebPart
{
    #region Properties
 
    private string strSourceList = string.Empty;
    private string strViewOfSourceList = string.Empty;
    private string strQuery = string.Empty;
 
    /// 
    /// The List we are displaying
    /// 
    [Personalizable(true),
    WebBrowsable(),
    WebDisplayName("List Name"),
    WebDescription("Pass the name of the List to show")]
    public string SourceList
    {
        get
        {
            return strSourceList;
        }
        set
        {
            strSourceList = value;
        }
    }
 
    /// 
    /// The Default View of the list
    /// 
    [Personalizable(true),
    WebBrowsable(),
    WebDisplayName("View"),
    WebDescription("Pass the name of the View that you want to apply to the List")]
    public string ViewOfSourceList
    {
        get
        {
            return strViewOfSourceList;
        }
        set
        {
            strViewOfSourceList = value;
        }
    }
 
    /// 
    /// a CAML query to filter the object
    /// 
    /// 
    /// in a later revision we will use one or more filter providers to set this
    /// 
    [Personalizable(true),
    WebBrowsable(),
    WebDisplayName("Query"),
    WebDescription("Pass the Filter Query")]
    public string FilterQuery
    {
        get
        {
            return strQuery;
        }
        set
        {
            strQuery = value;
        }
    }
 
    #endregion
 
    public CustomListViewWebPart()
    {
        this.ExportMode = WebPartExportMode.All;
    }
 
    protected override void CreateChildControls()
    {
        base.CreateChildControls();
        
        SPWeb web = SPContext.Current.Web;
        {
            try
            {
                SPList list = web.Lists[SourceList];
 
                // create the toolbar, actually we cannot hide it, we'll need to extend the webpart and those options
                ViewToolBar toolbar = new ViewToolBar();
                SPContext context = SPContext.GetContext(this.Context, list.Views[ViewOfSourceList].ID, list.ID, SPContext.Current.Web);
                toolbar.RenderContext = context;
                Controls.Add(toolbar);
 
                // get a reference to the view we want to use
                SPView webPartView = web.Lists[SourceList].Views[ViewOfSourceList];
               
                // create a new view based on the original one and attach the filter query to it
                // in this way we do not need to modify/update the original element and
                // even a user without updating permissions can use this webpart
                XmlDocument domDoc = new XmlDocument();
                domDoc.LoadXml(webPartView.SchemaXml);
                SPView view = new SPView(list, domDoc);
                view.Query = FilterQuery;
 
                // render the view
                Literal lbl = new Literal();
                lbl.Text = view.RenderAsHtml();
                this.Controls.Add(lbl);
            }
 
            catch (Exception ex)
            {
                // todo: have a better way to report errors!
                Label lbl = new Label();
                lbl.Text = "Error occured: ";
                lbl.Text += ex.Message;
                this.Controls.Add(lbl);
            }
        }
    }
 
    protected override void Render(HtmlTextWriter writer)
    {
        EnsureChildControls();
        base.Render(writer);
    }
}

To use it, just instantiate it on a page and set the ‘List’, ‘View’ and optionally ‘Query’ properties to the right values.

On the next articles of this series I’ll show you how to create custom filters and wire them to an evolved version of this WebPart.



Sharepointwsscustomlistviewwebpart

5 comments

WPF: yet another way to customize buttons controls (and controls in general)

Print Content | More

Days ago I needed a way to add an image and some other extensions to the standard button controls in WPF, I did a similar thing in the past in SIlverlight, but I had to rewrite the full control template.

I wanted to avoid this situation, so I started looking around and I found two very good post on the subject:

WPF Control Development - 3 Ways to build an ImageButton

Using Attached Properties to Create a WPF Image Button

Both those approach are good but they didn’t satisfied me in full: bad support for templating in the first case, and too much xaml to write in the second. So I merged both approach and came out with a solution that fulfills my needs:

  1. I created and inherited control
  2. I added some dependency properties to use it in xaml (that is specify the image)
  3. I used the ‘ContentTemplate’ and ‘DataTemplate’ features to define the style of the control (replacing the facto the standard content of the button.

Here’s the new button class:

public class ImageButton : Button
{
   static ImageButton()
   {
      DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton), new FrameworkPropertyMetadata(typeof(ImageButton)));
   }
 
   public ImageButton()
   {
      this.Loaded += new RoutedEventHandler(ImageButton_Loaded);
   }
 
   /// <summary>
   /// this event is used to adapt the style in case the control is used in a toolbar
   /// </summary>
   /// <param name="sender"></param>
   /// <param name="e"></param>
   void ImageButton_Loaded(object sender, RoutedEventArgs e)
   {
      if (Style == null && this.Parent is ToolBar)
      {
         Style = (Style)FindResource(ToolBar.ButtonStyleKey);
      }
   }
   
   public ImageSource Image
   {
      get { return (ImageSource)GetValue(ImageProperty); }
      set { SetValue(ImageProperty, value); }
   }
 
   // Using a DependencyProperty as the backing store for Image.  This enables animation, styling, binding, etc...
   public static readonly DependencyProperty ImageProperty =
       DependencyProperty.Register("Image", typeof(ImageSource), typeof(ImageButton), new UIPropertyMetadata(null));
 
}

And here’s the template (to be placed in the generic.xaml file)

<Style TargetType="{x:Type Buttons:ImageButton}" BasedOn="{StaticResource {x:Type Button}}">
   <Setter Property="ContentTemplate">
      <Setter.Value>
         <DataTemplate>
            <StackPanel Orientation="Horizontal">
               <Image Source="{Binding Path=(Image),
                    RelativeSource={RelativeSource FindAncestor,
                    AncestorType={x:Type Buttons:ImageButton}}}" />
               <TextBlock
         Text="{TemplateBinding Content}"
         HorizontalAlignment="Center" />
            </StackPanel>
         </DataTemplate>
      </Setter.Value>
   </Setter>
</Style>

Here the trick is to use the ‘BasedOn’ attribute of the Style, In this way we can inherit from the standard control template and override only the attribute we want to change.

The usage of this class now satisfies me:

<Buttons:ImageButton Content="Save" IsEnabled="{Binding AllowEdit}" 
                     Click="BtnSave_Click" 
                     Image="/XXXX.Warehouse;component/Images/save-alt.png" />

A similar approach can be followed to customize any other WPF control.

Button, Control, Customize, Image, Wpf

4 comments

VSeWSS: how to solve the ‘SecurityException: Access denied’ issue

Print Content | More

I started using VSeWSS as a support tool to develop a WSS/SharePoint application and I had to face some common issues. Sometimes when you try to ‘build and deploy’ - hum...this sentence sounds somewhat familiar :D - your solution you’ll get this exception reported (in the detailed log that VSeWSS emits):

System.Security.SecurityException: Access denied.
   at Microsoft.SharePoint.Tools.Reflection.ReflectionUtility.InvokeMethod(MethodBase method, Object instance, Object[] parameters)
   at Microsoft.SharePoint.Tools.Reflection.ReflectionUtility.InvokeMethod(Type type, String methodName, Object instance, Object[] parameters)
   at Microsoft.SharePoint.Tools.SharePointProxies.SPProxy.InvokeMethod(String name, Object[] parameters)
   at Microsoft.SharePoint.Tools.SharePointProxies.SPSolutionCollectionProxy.Add(String path)
   at Microsoft.SharePoint.Tools.SharePointProxies.SPSolutionFacade.AddSolution(String url, String solutionFilePath, Boolean solutionContainsWebApplicationResource)
   at VSeWSS.Server.Services.SPService.AddSolution(String url, String solutionFilePath, Boolean solutionContainsWebApplicationResource)
The Zone of the assembly that failed was:
MyComputer

As you can see you do not have many clues on what’s going on under the hood...It must be a problems related to the permissions under which the User related to the application pool under which the VSeWSS web service runs. In my case it runs with the same application pool of the SharePoint Central Administration Console, and it uses a custom user I called SharePointDB (take a look at my old series of articles about how to setup WSS/SharePoint).

For the things to work correctly this user must be a member of the following groups: Administrators, WSS_ADMIN_WPG, WSS_RESTRICTED_WPG.

Edit: Romeo Pruno (http://www.nonaka.eu/) pointed me out that the same problem can happen if the current user (or the account under which you run Visual Studio) is not a WSS/SharePoint Farm administrator.

After changing the Groups to which the user is associated to, perform an ‘iisreset’ and then try to deploy the project again.



Access denied, Sharepointwssvsewsssecurityexceotion

1 comments

VSeWSS: how to solve the WebNotFoundException

Print Content | More

I started using VSeWSS as a support tool to develop a WSS/SharePoint application and I had to face some common issues. Sometimes when you try to ‘build and deploy’ your solution you’ll get this exception reported (in the detailed log that VSeWSS emits):

Microsoft.SharePoint.Tools.WebNotFoundException: No SharePoint Site exists at the specified URL: http://XXXXXX. The Web application at http://sharepntdev could not be found. Verify that you have typed the URL correctly. If the URL should be serving existing content, the system administrator may need to add a new request URL mapping to the intended application. ---> System.IO.FileNotFoundException: The Web application at http://sharepntdev/ could not be found. Verify that you have typed the URL correctly. If the URL should be serving existing content, the system administrator may need to add a new request URL mapping to the intended application.
   at Microsoft.SharePoint.SPSite..ctor(SPFarm farm, Uri requestUri, Boolean contextSite, SPUserToken userToken)
   at Microsoft.SharePoint.SPSite..ctor(String requestUrl)
   --- End of inner exception stack trace ---
   at Microsoft.SharePoint.Tools.SharePointProxies.SPProxyUtility.GetWeb(String url)
   at Microsoft.SharePoint.Tools.SharePointProxies.SPWebFacade.GetWeb(String url)
   at VSeWSS.Server.Services.SPService.GetWeb(String url)

It tells you the URL in which he’s trying to deploy your facility. To correct that just open the project properties and go to the ‘Debug’ tab, then insert the correct URL in the field ‘Start browser with URL:’ like in the following screenshot:

WebNotFoundExceptionProjectProperties



Sharepointwssvsewss, Webnotfoundexception

3 comments

WPF: force all the validation rules attached to an object to be executed

Print Content | More

I’m working on a WPF application that have some validation performed through the standard ValidationRule system employed by WPF at the UI level.

Recently I needed a way to validate (that is check the state and force the execution of any validation rule) full portions of the Visual Tree. The idea was to call a function that, given a DependencyObject would traverse the tree and force the execution of any validation rule attached to a any Binding we can find.

The first step is then find out how to get all the Dependency Properties that an object exposes; I’ve ‘googled’ a bit and found out many solution that use the DependencyObject.GetLocalValueEnumerator() method...unfortunately this one is not useful in my case, cause it doesn’t return values set in templates.

In the end I was forced to use reflection to get the dependency properties of an object and for performances reasons I decided to cache the result of those reflection calls in a dictionary.

The rest of the function is straightforward and it’s a modified version of a routine you can find on the ‘Programming WPF’ book. To force the validation to be performed instead of calling the Validation.MarkInvalid() function I choose to get the binding expression and call it’s update methods which guarantee that the associated error collection of an object is cleared if the state becomes valid again.

Here’s some code:

public static class Validator
{
   private static Dictionary<Type, List<DependencyProperty>> PropertiesReflectionChace = new Dictionary<Type, List<DependencyProperty>>();
 
   private static List<DependencyProperty> GetDPs(Type t)
   {
      if (PropertiesReflectionChace.ContainsKey(t))
         return PropertiesReflectionChace[t];
      FieldInfo[] properties = t.GetFields(BindingFlags.Public | BindingFlags.GetProperty |
           BindingFlags.Static | BindingFlags.FlattenHierarchy);
      // we cycle and store only the dependency properties
      List<DependencyProperty> dps = new List<DependencyProperty>();
 
      foreach (FieldInfo field in properties)
         if (field.FieldType == typeof(DependencyProperty))
            dps.Add((DependencyProperty)field.GetValue(null));
      PropertiesReflectionChace.Add(t, dps);
 
      return dps;
   }
 
   /// <summary>
   /// checks all the validation rule associated with objects,
   /// forces the binding to execute all their validation rules
   /// </summary>
   /// <param name="parent"></param>
   /// <returns></returns>
   public static bool IsValid(DependencyObject parent)
   {
      // Validate all the bindings on the parent
      bool valid = true;
      // get the list of all the dependency properties, we can use a level of caching to avoid to use reflection
      // more than one time for each object
      foreach (DependencyProperty dp in GetDPs(parent.GetType()))
      {
         if (BindingOperations.IsDataBound(parent, dp))
         {
            Binding binding = BindingOperations.GetBinding(parent, dp);
            if (binding.ValidationRules.Count > 0)
            {
               BindingExpression expression = BindingOperations.GetBindingExpression(parent, dp);
               switch (binding.Mode)
               {
                  case BindingMode.OneTime:
                  case BindingMode.OneWay:
                     expression.UpdateTarget();
                     break;
                  default:
                     expression.UpdateSource();
                     break;
               }
               if (expression.HasError) valid = false;
            }
         }
      }
 
      // Validate all the bindings on the children
      for (int i = 0; i != VisualTreeHelper.GetChildrenCount(parent); ++i)
      {
         DependencyObject child = VisualTreeHelper.GetChild(parent, i);
         if (!IsValid(child)) { valid = false; }
      }
 
      return valid;
   }
}


Binding, Error, Validation, Validation rule, Wpf

8 comments

UI Prototyping: simplify your life with Balsamiq

Print Content | More

Recently I attended the UGIALT.NET Conference and the first session was devoted to How to Design the User Experience, the speaker - Daniela Panfili - clearly stated some good points and she told us how she and her team spend a lot of time interacting with the end user and designing the user interface; the purpose is to try to offer the right functionalities in the right place to maximize the usability of the application, keeping however an eye on the look and feel to have a pleasant interface.

I have to admit I was always been focused in developing the architecture of an application first, that is the usual tasks: design application modules, glue them with an IoC container or a plug-in system, define some communication methods, use patterns like AoP and similar to inject logging function and so on...

Usually I left the interaction with the user as the last thing, or something that only the functional analysts have to care about at start (and if they are good they do their job well, if they are so so or inexperienced you often end up rewriting their job..which is a big loss of time)…in recent times I’ve however started to change my mind especially when I saw what came out from some designs: applications that have all the required features but they are ‘hidden’ or hard to be found by the users…so I started to draw some sketches by hand to figure out how the application should look and work.

The basic idea is to have a better picture of what the user want and how it should use it before starting to write any architectural code; in an ideal situation you should have two different design pipelines: one for the UI and UX and one for the architecture, they both can start work in parallel, while you are working on the generic infrastructure or framework on top of which you develop your architecture.

Having sketches of how the application should look (I’m not talking about astonishing graphic effects or animation, but the general disposition of the elements) also is very useful to integrate the documentation and give the client some immediate feedback on what the project will be.

Doing the whole job by hand can be fast but it has some drawbacks: you need to perform periodic scans of the sketches and put them in your repository, they get messy pretty fast (you don’t have any Undo feature when it come to the good old paper), only one person can have the original copies, and it’s hard for different people to work on the design (especially if they are in different locations).

Having a good tool that allow everyone to draw or modify a sketch is starting to be a necessity in teams that want to develop software seriously, it’s true we have a plethora of Paint-like and PowerPoint-like apps around; but they require skills that not all the developers have or have time to learn.

Here’s where Balsamiq come help us, this tool is specifically designed to allow even non-non professional graphic artists to design and prototype interfaces and functionality pretty fast. It’s very intuitive and easy to use and allows everyone – with a minimal effort – to draw a detailed scheme of what the UI will resemble to.

Using a tool like this can also help you realize if you are doing a good job in defining your UI...to test it a bit I tried to replicate an interface I’ve wrote for a warehouse designer tool to be used in a project; down here you can see the result.

BalsamiqWarehouseDesignerMockup

While writing it in WPF I thought it could be a good interface design...well...giving it a second look here I realized that my job, even if it had all the required features, wasn’t good enough and I’m actually looking at how I can improve it.

Balsamiq comes with a quite complete library of common controls and it can be extended easily, there are in-fact a series of template freely available. Balsamiq allows you to add a level of interaction between different mockups and provide links to them, so you can simulate some navigation in the user interface. You can also export the mockup design in XML to process it with your custom utilities or generate a Flex application (a service offered by a 3rd party company).

In short a tool that can help raise your productivity, especially in the early stages of developing of a new project.



Balsamiq, Interface, Prototyping, Ui

7 comments