Welcome to SofiaDev.Org's Blogs Sign in | Join | Help

Running Intel Core Duo

I’ve just got my new Toshiba Portege M400 – my first Intel Core Duo and Tablet PC @ the same time. And it’s great. It came just a couple of days before I went back to Sofia, for DevDays 2006.

However, I think Toshiba has some problems with the preinstalled software they ship. A colleague orf mine has the same (although he’s not a Dev) and he shared with me that he has some major problems with the performance. It turned out (at least for me) that when I run virtual machines, for example, I get much better performance after I’ve uninstalled Toshiba Bluetooth Stack – a sort of a pack of drivers and software for managing and working with Bluetooth devices that came with the preinstalled OS. The bad thing is that so far I haven’t found another way of enabling Bluetooth on my tablet – MS’s drivers that come with XP SP2 doesn’t seem to find the hardware components. And I need those, because I want to be able to use Internet over GPRS (which is pretty cheap in The Netherlands these days – 10 EUR per a month for unlimited access). So I’ll keep searching.

posted by branimir | 0 Comments

Intellisense for MS SQL Server 2000/2005

There’s a limited time free of charge offer by Red Gate Software for their product “SQL Prompt”. Check it out @ http://www.red-gate.com/products/SQL_Prompt/index.htm

posted by branimir | 0 Comments

Generic event-handlers in .NET 2.0

I was writing-up an event handler with custom event arguments, getting ready for defining the event args class along with a delegate for the event definition (as you’re supposed to in .NET 1.1), when I’ve noticed that in VS intellisense is helping me with an advice saying that I can use a generic event argument. Cool !!!

So I’ve decided to take a couple of minutes off and see what’s can I do with .NET 2.0.

In .NET 1.x, we had to do the following:
  1. Define a delegate type that holds the signature for the even type.
  2. Define a custom class that inherits from System.EventArgs.
  3. Define a class that will raise the the event instance
  4. And encapsulate an event of the delegate type in the class from #2.
  5. Attach event handlers for the event
  6. And then consume the event

Here’s a simple event definition compatible with MS.NET 1.1 (and still working in 2.0)

 

using System;

namespace SofiaDev.Events.dn11
{
      public delegate void CustomEventHandler(object sender, CustomEventArgs e);

      /// <summary>
      /// Event Args class. Holds data, specific for the event instance.
      /// </summary>
      public class CustomEventArgs : System.EventArgs
      {
            private DateTime m_dtEventSend;
            private string m_strMessage;
           

            /// <summary>
            /// returns a message send to the mesasge subscriber.
            /// </summary>
            public string Message
            {
                  get { return m_strMessage; }
            }
            /// <summary>
            /// another specific field for the event subscriber
            /// </summary>
            public DateTime DateEventSend
            {
                  get { return m_dtEventSend;  }

            }           

            /// <summary>
            /// Initializes a new instance of the custom event arg instance
            /// </summary>
            public CustomEventArgs(string message, DateTime dateEventSend)
            {
                  m_strMessage = message;
                  m_dtEventSend = dateEventSend;
            }
      }
}

 

So that’s the event args definition and the delegate.
Then we need the class that does the incapsulation and raises the event. 

Like this:

 

using System;
using
System.ComponentModel;
using
System.Threading;
 

namespace SofiaDev.Events.dn11
{
      /// <summary>
      /// Class that raises events of the type we've defined in dn11_Event.cs
      /// </summary>
      public class SomeClassThatRaisesEvent
      {
            /// <summary>
            /// This is the event subscription hook. You should attach you're handler to it. When the moment is right, the class will
            /// call your handler with the appropriate event args data.
            /// </summary>
            public event CustomEventHandler CustomEvent;
           

            /// <summary>
            /// This method actually does the calling. If the event handler queue is not empty, it should call
            /// the delegate, passing the appropriate event arguments.
            /// </summary>
            /// <param name="e"></param>
            protected virtual void OnCustomEvent(CustomEventArgs e)
            {
                  if ( null!=CustomEvent )
                  {
                        CustomEvent(this, e);
                  }
            }
           

            /// <summary>
            /// calls a method that will return in 2 seconds
            /// </summary>
            public void CallEventhandlersIn2Seconds()
            {
                  BackgroundWorker bgw = new BackgroundWorker();
                  bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
                  bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
 

                  bgw.RunWorkerAsync();
            }
 

            /// <summary>
            /// Actual work being done here.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void bgw_DoWork(object sender, DoWorkEventArgs e)
            {
                  Thread.Sleep(2000);
            }

 
            /// <summary>
            /// we'll call the event handler from here.
            /// </summary>

            void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {

                  string strMessage = string.Format("hello from the second thread at {0}", DateTime.Now.ToString("dd-MM-yyyy hh:mm:ss"));
                 

                  //init the custom event args instance with specific data
                  CustomEventArgs args = new CustomEventArgs(strMessage, DateTime.Now);
                 

                  //call our internal method that does the actual call of the events on clients.
                  OnCustomEvent(args);
            }
      }
}

 

In this one, we have a couple of additional methods that will help us demonstrate the event call itself.  Check out the comments for more info.

Then we can use the whole thing. Like this:
 

using System;
using
System.Collections.Generic;
using
System.Text;
using
System.Threading;
using
SofiaDev.Events.dn11;

namespace EventArgs
{
      class Program
      {
            static bool StillWaiting = true;           

            static void Main(string[] args)
            {
                  //init the instance that will we're gonna be waiting on.
                  SomeClassThatRaisesEvent instance = new SomeClassThatRaisesEvent();
 

                  //attach an event handler of our own
                  instance.CustomEvent += new CustomEventHandler(instance_CustomEvent);                 

                  //call method that will call us in a couple of secs (when he's ready
                  instance.CallEventhandlersIn2Seconds(); 

                  Console.WriteLine("about to start waiting");

                 

                  while ( StillWaiting )
                  {
                        Console.Write(".");
                  }

                
                  Console.WriteLine("\n\nExiting!!!");
            }

             static void instance_CustomEvent(object sender, CustomEventArgs e)
            {
                  Console.WriteLine("\nCall returned. ");
                  Console.WriteLine("Message: {0},\ndate: {1}", e.Message, e.DateEventSend.ToString());

 
                  StillWaiting = false;
            }
      }
}

 

The problem here is that when you author an extensive library, it takes a lot of time to do the same code over and over again.

The new thing in .NET 2.0, is the possibility to use a generic delegate (there is one within the .NET BCL already) and use it everywhere. To be able to do that, you only need to define your custom event class holding the data specific to your event. In fact we can use the same class declaration as in the .NET 1.1 example and still be able to use a generic delegate as the event type.

Here’s how the same class will look with a generic event declaration:

 

using System;

namespace SofiaDev.Events
{
      /// <summary>
      /// same class as in the .NET 1.1 example
      /// </summary>
      public class SomeClassThatRaisesEvent
      {
            /// <summary>
            /// Only this time the event handler will have a generic definition
            /// </summary>
            public EventHandler<CustomEventArgs> CustomEvent;

          
            protected void OnCustomEvent(object sender, CustomEventArgs e)
            {
                  if (null != CustomEvent)
                        CustomEvent(this, e);
            }
      }
}

 

An example solution with both ways of doing the event declaration is available as an attachment.



posted by branimir | 0 Comments
Attachment(s): EventArgs.zip

Comparing and Sorting with Generics

I’m working on a project on which I need to sort some custom classes. Today, I’ve decided to play around and find easier and faster way to deal with different sorting scenarios with the use of generics.

I’ve a simple class hierarchy with a root abstract class called DataObject. From there I’ve inherited with a number of implementation classes that are used as a data containers (I’m using nHibernate for accessing the data in my MS SQL database).

I need to be able to sort arrays of instances of my data container classes. Some of them by a property A, and other by property B. Property A and B might have different types (string and int for example), and I don’t want to write a number of IComparer implementations.

So, I wrote that:

using System;
using System.Collections;

namespace SofiaDev.Generic
{
      public abstract class DataObjectSortableBy<T> : DataObject, IComparer where T : IComparable<T>
      {
            protected abstract T SortOnThisField
            {
                  get;
            }

            public virtual int Compare(object o1, object o2)
            {
                  T t1 = ((DataObjectSortableBy<T>)o1).SortOnThisField;
                  T t2 = ((DataObjectSortableBy<T>)o2).SortOnThisField;

                  if (null != t1 && null == t2)
                        return 1;
                  if (null == t1 && null != t2)
                        return -1;
                  if (null == t1 && null == t2)
                        return 0;

                  return t1.CompareTo(t2);
            }           

            public abstract object Empty
            {
                  get;
            }
      }
}

Now I can define base abstract classes for sorting.
Like this:

namespace SofiaDev.Generic
{
      public abstract class DataObjectSortableByString : DataObjectSortableBy<string>
      {

      }

      public abstract class DataObjectSortableByInt : DataObjectSortableBy<int>
      {

      }
}

 

And then inherit from them and oiverride the SortOnThisField method.

.NET RULEZ :)

posted by branimir | 0 Comments

WSE 2.0 and Windows Authentication

I’m currently finishing on a project which uses WSE 2.0 SP3 as a communication platform. At one point I’ve had an interesting problem, which I couldn’t find solution for (at least not according to the specs and WSE documentation). So I’ve decided to share my knowledge on the matter and how I’ve solved it, in case anyone else finds it difficult to deal with a similar situation.

So what’s the problem?

I was implementing a SOAP over SMTP messaging infrastructure for sending XML messages through email, because of the fact that the backend of the application can’t be published on the internet for security reasons. So we’ve done a proof of concept (Paul did that) which was working like a charm.

Then when I took over and started to put the whole thing together, I’ve got a strange problem with a web service published in WSS site, which was called through the Soap over Smtp “component”. The problem was, that Sharepoint needs a windows identity that should be verified by IIS (sharepoint uses IIS for the authentication process). So even if you do a local LogonUser, WSS/SPS won’t be happy because of some strange reason that I couldn’t find. So now I had to make the call on the behalf of a user that has to be authenticated against IIS (so Active Directory or a local Windows account) and then, eventually I was going to be able to do my thing in Sharepoint. That means that along with the message relay though my SoapReciver, I had to send a windows identity. It turned out that this is not an easy thing to do with WSE 2.0 (SP3). Smile [:)]

What did I try?

1. Obtaining the context of the SoapHttpOutputChannel and setting the PreAuthenticate property to true, along with the Credentials to System.Net.CredentialCache.DefaultCredentials (my service that relays the messages is logged on the same machine, so I should have been able to use the credentials).

The “obtaining” part was done in a custom SoapOutputFilter that was called for every message that was send.

That doesn’t work.

It fails with a strange exception, that has been partially documented with ASP.NET 1.1, but doesn’t work with ASP.NET 2.0 as well. How to test it and see that it doesn’t work? Here’s a simple program that’s sending a single message to a very, very simple web service:

try
{
      SoapEnvelope message = new SoapEnvelope();
      message.Context.Addressing.Action = new Action("http://tempuri.org/HelloWorld");

      Uri urlTo = new Uri("http://localhost:7357/WSTest/Service.asmx");
      SoapSender sender = new SoapSender(urlTo);

      message.Body.InnerXml = "<HelloWorld xmlns=\"http://tempuri.org/\" />";
      sender.Send(message);
}
catch ( Exception ex )
{
      Console.WriteLine(ex.Message);
      Console.WriteLine(ex.StackTrace);
}

And here is the filter that’s been called:

public class Output : SoapOutputFilter
{
      public override void ProcessMessage(SoapEnvelope envelope) 
      {
            if ( null!= envelope.Context )
            {
                  ISoapChannel channel = envelope.Context.Channel;
                  SoapHttpOutputChannel httpChannel = channel as SoapHttpOutputChannel;                 

                  if ( null!=httpChannel )
                  {
                        httpChannel.Options.PreAuthenticate = true;
                        httpChannel.Options.Credentials = CredentialCache.DefaultCredentials;
                  }
            }
      }
}

 

And finally, here’s the exception:

The operation has timed-out.
   at System.Net.HttpWebRequest.GetRequestStream()

   at Microsoft.Web.Services2.Messaging.SoapHttpTransport.Send(SoapEnvelope mess

age, EndpointReference destination, SoapHttpChannelOptions options)
   at Microsoft.Web.Services2.Messaging.SoapHttpOutputChannel.Send(SoapEnvelope message)
   at Microsoft.Web.Services2.Messaging.SoapSender.Send(SoapEnvelope envelope)   at ConsoleTest.TheMainClass.Main(String[] args) in c:\documents and settings\branimir\my documents\visual studio projects\consoletest\main.cs:line 29


If you want to test it yourself, download the code and run it. The web service is a ASP.NET 2.0 WS, so you need that installed. Along with WSE 2.0 SP3 for the console app.

2. Obtaining the SoapHttpOutputChannel before sending the message. Doesn’t work as well. The problem here is that sending the message has nothing to do with what protocol will be used for that. You should be able to add or remove protocols though the configuration of the app, so this way you can replace the default Http sender with a custom HttpSoapTransport. That really makes sence. Actually this is how I finally cracked it :) – see #3 for details on this one.

I’ve tried the following to get a reference to the SoapHttpOutputChannel instance:

 

EndpointReference endpoint = new EndpointReference(urlTo);
ISoapTransport transport = SoapHttpTransport.GetTransport(endpoint);
SoapHttpTransport httpTransport = transport as SoapHttpTransport;


if
( null!=httpTransport )
{
      SoapHttpOutputChannel httpOutputChannel = 
            httpTransport.GetOutputChannel(endpoint, SoapChannelCapabilities.None) as SoapHttpOutputChannel;

      
      httpOutputChannel.Options.Credentials = CredentialCache.DefaultCredentials;

      httpOutputChannel.Options.PreAuthenticate = true;
}

3. Replacing the default SoapHttpTransport with a custom implementation that does the authentication by default. It’s not so easy to write that (and test it so you can be sure that it works).
So I’ve decided to decompile what Microsoft did, and customize it.
Then I’ve added a new protocol scheme for using integrated authentication called “http.auth://” and used it when I wanted to make calls that authenticate with Windows Integrated.

Check out the attachments for this post for the complete source code.

Initially I wanted to just change the default options of the default SoapHttpTransoport, but that turned out the be impossible. I kept getting the same exception as in #1.

So I’m guessing that there is a problem with the Options of the protocol (don’t think that they’ve tested it good enough – the options are not getting initialized anyway).

At that point I’ve already decompiled MS’s implementation and I’ve filled in the gaps, so it was actually working. I’ve added a couple of lines of code to  the method that does the actual call and it was ready. It actually worked Smile [:)]. Wohooo - I have a SoapHttpTransport with a Windows Authentication of my own, and it's working Smile [:)].

If you wan to use this one, once you complile the transport, you need to add the following lines to your config file (the wse2 section should be there already):

  <microsoft.web.services2>

    <messaging>

            <transports>

                  <add scheme="http.auth" type="SofiaDev.Wse.SoapHttpTransport, SofiaDev.Wse" />

            </transports>

    </messaging>

  </microsoft.web.services2>

Then, use http:auth:// as a transport scheme instead of http. This way WSE knows which transport  protocol implementation to instantiate, based on what it finds at the config file.

posted by branimir | 0 Comments
Attachment(s): WSE Files.zip

Accessing Active Directory without specifying LDAP path

I’m writing up a class that wraps all of the functionality I need for accessing AD in one place.
So how do I get the LDAP path to the domain controller?

It’s easy – just get it from AD itself. Here’s the code:

using (DirectoryEntry rootDse = (PreAuthenticate ? new DirectoryEntry("LDAP://rootDSE", Username, Password) : new DirectoryEntry("LDAP://rootDSE")))

{

      if (null == rootDse)

      {

            throw new ApplicationException("Can't connect to LDAP://rootDSE. Please make sure that the computer on which you're trying to run the component is a member of the domain and is currently connected to at least one DC.");

      }

 

      TypedPropertyValueCollection<string> prRootDse = new TypedPropertyValueCollection<string>(rootDse, "defaultNamingContext");

      TypedPropertyValueCollection<string> prDomainName = new TypedPropertyValueCollection<string>(rootDse, "dnsHostName");

 

      RootDSE = prRootDse.Value;

      DomainName = prDomainName.Value;   

}

 

Then you can get the LDAP Path like this:

 

static string LdapPath

{

      [System.Diagnostics.DebuggerStepThrough]

      get

      {

            return string.Format("LDAP://{0}/{1}", DomainName, RootDSE);

      }

}

 

 

The other interesting thing here's the TypedPropertyValueCollection<T> which I've used to whar the access to System.DirectoryServices.DirectoryEntry's properties.

With that I won't have to check for the entry being != null, then casting it to something, etc. Here's the example code:

namespace SofiaDev.DirectoryServices
{
      class TypedPropertyValueCollection<T> where T: class

      {

            System.DirectoryServices.PropertyValueCollection m_property;

 

            public TypedPropertyValueCollection(System.DirectoryServices.PropertyValueCollection property)

            {

                  m_property = property;

            }

 

            public TypedPropertyValueCollection(System.DirectoryServices.DirectoryEntry directoryEntry, string propertyName)

            {

                  m_property = directoryEntry.Properties[propertyName];

            }

 

            public T Value

            {

                  get

                  {

                        return m_property.Value as T;

                  }

            }

 

            public string PropertyName

            {

                  get

                  {

                        return m_property.PropertyName;

                  }

            }

 

            public bool IsNull

            {

                  get

                  {

                        return ((null != m_property) && (null != m_property.Value));

                  }

            }

      }

}

 

The complete source of two classes can be found in the attachment of the post.

 

Also in there you can find a couple of quick Find methods (one for searhing user by principal name and one for searching users by email address.

Using nHibernate with .NET Framework 2.0 and a generic data factory implementation.

One of the projects currently I’m working on is using nHibernate as a data persistence framework. If you’re not familiar with the concept, check out Nikola’s article on nHibernate.

 

Ideally we want to write as little as possible code that deals with data access, and be able to stay in control on what’s happening with the data access at the same time, nHibernate is a great tool for doing that. In this post we’ll take a look at the usage of nHibernate with MS .NET 2.0 and especially with the use of generics. I’ve written a simple generic data factory class that does provide everything we’ll need for all of the data access in our application.

 

In addition, I’ve found an interesting behavior while trying to use assigned Id generator within my mapping classes. What is it about? Well – it doesn’t work as you might expect it to. Because of some strange reason (or maybe a bug) – I don’t know. I didn’t have the time to investigate ‘till now, so I’ll leave that for a later post.

 

So what’s the data model, and what do we want to achieve?

 

We’ll start with a single entity – contact’s picture, which has three fields:

-          ID of int

-          ImageType of string

-          And the image itself with is going to be stored in the DB in an image field.

 

The class definition looks like this:

Here we have all of the fields I’ve described already along with a two more – an ID and TableName. Those two are being used in the Search class in my app where I need to be able to generate dynamically SQL statements. They come from a base abstract class, called DataObject.

 

The mapping file (which specifies how nHibernate should do the mapping from the DB into the classes and the other way around looks like this:

 

<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" namespace="SofiaDev.nHibernate.Data" assembly="nHibernateDemo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">

  <class name="ContactPicture" table="Images">

    <id column="ImageID" name="ImageID" type="System.Int32">

      <generator class="assigned" />

    </id>

    <property name="Image" column="TheImage" type="System.Byte[]" />

    <property name="ContentType" column="ImageType" type="System.String" />

  </class>

</hibernate-mapping>

 

 

So how do we retrieve and save data from and into the DB? Usually we would either have to define a base class that has a couple of basic Save() and Get() functions and continue recreating it (either inheriting or by the good-old copy/paste technique). Either way it’s something that takes a lotta time and can be excluded from the scope of our project.

 

In nHibernate we use a sort of a session context which hides the underlying connections and everything else we need in order to work with the data. For that reason I’ve defined a single class that takes care of the initialization of nHibernate, called InitializerFromSchema.

My class implements the Singelton pattern by hiding it’s constructor and exposing a single static property called Instance. The getter of the property needs to check if the instance has been initialized and if not, it needs to do that. Then it will return a reference pointing to the instance.

The instance itself holds a single instance of a class implementing NHibernate.ISessionFactory interface. That interface is what the outside world knows about nHibernate. Everything else is meant to be hidden for now.

So here’s the initializer:

 

 

Then we have a generic class – our data factory that deals with the instantiation of the correct typed data access component.

This one is going to be instantiated with a reference to a type, which will be the type we’ll access the data for.

 

A simple instantiation of the factory with our simple ContactPicture class looks like this:

 

DataClassesFactory<ContactPicture> picFactory = new DataClassesFactory<ContactPicture>();

 

try

{

      picFactory.Insert(pic);

}

catch (Exception ex)

{

      Console.WriteLine(ex.Message);

}

 

Where the pic variable is actually an the instance we want to save into the database.

Check out the attachment for the complete solution along with the source code.

posted by branimir | 0 Comments
Attachment(s): ConsoleApplication4.zip

Passed 70-529 - TS: Microsoft .NET Framework 2.0 - Distributed Application Development

I was checking my profile at Vue this Friday, when I saw that the results for 50-529 are finally out. I've passed :). With this one I've 2/4 of the new .NET track passed in beta.
posted by branimir | 0 Comments

And here's the actual SPList implementation

So let’s pick it off from where we’ve left the last time. We’ve defined some base classes we’re going to use throughout our solution:

  • BaseList – abstract base class
  • An abstract configuration
  • A concrete implementation of the configuration
  • And a configuration factory, which was taking care of the initialization process of the instance of the configuration class.

Today, we’ll add something more practical to the solution. We’ll define a concrete instance of the SPList (by inheriting from it and adding some additional methods).

So the purpose is to be able to work with custom list – one that is a part of either a WSS or a Sharepoint site.The list might have to be exposed for use in an external application – like let’s say a smart client application, though a web service. But how do we do that? Do we have to define references to the Microsoft.Sharepoint assembly at the client side in order to do that? Well, we better don’t ‘couse that doesn’t sound like a good design decision, does it :).

So how can we expose a list through a web service for usage from outside clients like smart client applications or even from apps based on platforms other than MS .NET? We’ll define a bunch of data container classes that will have the ability to serialize and de-serialize (with the use of [SerializableAtttribute] class from .NET). What that actually means, is that we’ll have to define the schema of the messages (our serializable classes will be a part of the schema) and then define a custom logic for converting the list items to those custom types.

So we need the following:

  • a list inheriting from the base class
  • a [ListItem] class (supporting serialization)
  • a custom logic for converting from SPListItem to the custom [ListItem] class instances.

So let’s say that we have a very simple list that has only two fields we’re interested in – a “Title” and a Guid.

The list definition should look like this:

 

We’ve mentioned that we’re interested in 2 fields, not one. The fact is that every list contains a bunch of fields that are hidden from the user. One of them is called "GUID" and is of type Guid, which maps to the System.Guid in the .NET Framework. The other field, we can also use as an identifier is the ID field of type int.

 

 

So as you see, we have two different Find methods, and one Convert method. The two different Finds will be used when we want the ability to get an instance of the SPListItem, when we know either the Giud or the integer ID of the item. Internally WSS and SPS use auto-increment for the most of the identities, so there’s a pretty good chance we’ll need both Guid and the integer ID.

 

 

 

posted by branimir | 0 Comments

Introduction to the SPS series - Defining a base class library

So let’s start with something simple. We’re going to define a few base classes, that will be used later on with all of the topics listed in the previous post. The base classes include:

  • A base abstract configuration class that will contain some info related to the metadata about the lists with which we’re going to work.
  • A configuration factory class, that will provide us with the instance of a class inheriting from the abstract config.
  • An implementation of the base config (just a simple hard-coded example).
  • A base abstract class, wrapping an instance of Microsoft.Sharepoing.SPList. It will take care of the initialization of the configuration settings, along with providing us with some basic operations like searching for items in the list through a SPQuery instance, and working with the views defined for the SPList instance. Throughout the next following posts (or small articles) we’ll extend the basic functionality of the class, by encapsulating more and more features inside the base class.

Here’s a small diagram, showing the base class, along with some details about the configuration and the way it’s using it:

 

 

The BaseList class inherits from System.Object (as all classes in the .NET world). It wraps an instance of the Microsoft.Sharepoing.SPList class and adds some metadata (as properties) relative for that list. The class has 2 constructors – first one listName, of type string and a second, that takes as input the name of the list and in instance of the Path. The Path class is a wrap for 2 properties, we’re gonna need on order to initialize the SPList instance – the address of the portal (the root – something like http://www.microsoft.com/) and a relative path under that root – the address of the sub web, we’re gonna mess with.

Now – why do we need 2 constructors? Well – it’s pretty simple – we’re gonna support more than one way of initializing the list. One way will be by using the list name. When we do that, the list instance will initialize itself with settings coming from the configuration (that will be hold inside the Path instance). Other way of initializing the instance will be with the explicit use of the portal and site path – a case that will apply when we work with a number of lists, and have some sort of a relation between them. Then the second constructor should become very handy.

But where the configuration info comes from? We’ve already mentioned that we’ll be using an abstract base class and will be able to have more than one child implementation classes (for example with a config info coming from DB, a Enterprise Library’s Configuration Application block or some other “data source”).

So here it is:


 

 

As you can see from the diagram, the abstract BaseConfig class, is just a “blueprint” – it has only 2 properties (for now). Underneath is the TempConfig – an implementation instance, that simply will return some hard-coded configuration information.

The trick here, is that won’t use the TempConfig explicitly – we’ll return an instance of it, but it will be cast as a BaseConfig – this way, we be able to move to a more mature class (or simply use different configuration, depending on the caller, or the buld we’ve done – using conditional compilation or something else)

And here’s the factory:

 

All it does, is holding an instance (because we want to stay with a single (singleton) instance for all callers, and returning info from the config “data source”.

That's all for now - more to come soon :)

 

 

posted by branimir | 0 Comments

Taking a crash course in Dutch at Spa, Belgium

I’m taking a crash course in Dutch this week. Since last Sunday, I’m taking a week crash course at Ceran’s center at Spa, Begium (www.ceran.com).

It is pretty intense and very interesting at the same time.
I’ve met some very interesting people down here – most of us (the students) come here for a different reason – some because of personal reasons, other because of their jobs (relocation of just a requirement because of some strange reason).
 
Anyway – I’m getting pretty good :)
posted by csadmin | 0 Comments

Already a Microsoft Certified IT Professional - Database Administrator

Got the results of some of the Beta MCP exams I took in December. So far, I'm qualifying for MCITPro - DBA.
I'm still waiting on the rest of the Beta's I took - 3 more and I have another 3 in about 10 days from now (MCSD upgrade and another SQL).

Wish me luck :)
posted by csadmin | 0 Comments

An interesting series of Expert-level SPS posts are about to get published here

I did quite a serious Sharepoint Portal Server development for the last couple of months, focusing on some interesting aspects of SPS. There are a few topics which I found difficult to find documentation and resources on, so I’ve decided to do a few blog posts about them. Here’s the list:

  • Working with SPView and SPQuery class.
  • Customizing SPView rendering on the fly: Using custom CAML queries for rendering a subset of a list in a view. Using grouping and sorting query results. Showing and hiding toolbar and titlebar of the view.
  • Working with SPQueryWorking with dynamic queries. Defining CAML on the fly, without having to hard-code XML into web parts. Defining queries with more than 1 condition. Working with different types of fields inside SPList class and in CAML. Using GroupBy in CAML.
  • Definition of a custom CAML generator (to be used with SPQuery and SPView). An example of a simple CAML generator in C# (I’m a C# MVP after all - need to do fancy stuff with C# from time to time, right:))
  • Customizing default SPListItem views in SPS and WSS.How to customize the DispForm.aspx, EditForm.aspx, etc. forms with WSS/SPS and SmartPart. How to find, hide and show the default controls inside those pages.
  • Getting info about the DispForm.aspx, EditForm.aspx, etc control ID’s from SPS metabase (hacking Sharepoint :))

That’s the list for now. I have the source code already – only need to write the posts and put them online. So I hope it won’t take long. Anyway, wish me luck :)

posted by csadmin | 0 Comments

Moving to The Netherlands

I've moved - since Jan 1 2005, I'm taking the position of Sr. Software Dev at Tam Tam (http://www.tamtam.nl).

Planning on a few articles on Dev with SPS - doin' a lot of it in the past month - especially working with SPList(s), SmartPart, controls inside SPS, etc. Have a pretty good basis for a nice article about how to wrap a list and create an effective class structure that can be reused in more than one project. So if I can find the time, I'll make sure thay I publish that :).
Cheers,
Branimir from NL :)
posted by csadmin | 0 Comments