Archive

Author Archive

IFilter for TIFF

March 3rd, 2010 No comments

Windows Server 2008 R2 comes OOTB with an IFilter, which allow the indexing of TIFFs. During the indexing the IFilter performs an OCR to recognize the actual content of the TIFF for the index.

This combined with a corresponding scanner introduces a small-sized DMS, where you can scan paper based documents to a document-library and let them being index and thus fully searchable by SharePoint.

Categories: SharePoint Tags: ,

Modifiy any page within SharePoint

February 27th, 2010 No comments

There is alway something new to discover. Usually when you want to edit a page in SharePoint you just hit “Website actions” “edit page”. But certain pages don’t offer to edit themself, such as the edit-form for list-items. So what?

Just append “toolpaneview=2” to the address of the currently visible page; and magically you’ll see the WebPart-Editor-Pane, which allows to edit the current page. This way you can literally edit every page in SharePoint.

Categories: SharePoint Tags:

SharePoint is nice, nice baby!

February 7th, 2010 No comments

Dux Raymond Sy performed at the Best Practices Conference 2009 in Washington a cool rap about how nice SharePoint is.

This is the original session:

and these are the slides presented at the session (among others):

Categories: Fun, SharePoint Tags:

Copy all content of a web application

February 7th, 2010 No comments

When developing web-applications using Visual Studio everything is quite easy. Especially since Microsoft introduced the development-web-server (aka Cassini) web-development is really smooth. Just create a new project and you’re ready to roll.

But there comes the point in time, where you want to deploy your web-app to a real server. So how can you accomplish this the best way? Well, using Visual Studio you can publish a web-application to a web-server using HTTP, FTP or a UNC path. But this is a manual step you would have to trigger.

Of course you could setup a copy-task, by using xcopy or something similar (like NAnt’s copy task). But this would mean, that you would have to specify all files that should be copied. Or you would have to use wildcards, by specifying all extensions which should be copied. But what happens when you add some unusual (or new) file to the project? This will most likely not being copied and you’ll have to remember to modify your copy-task.

For that purpose MSBuild has a special task called _CopyWebApplication, which is part of the Microsoft.WebApplication.targets. This task will copy all items of our web-application project, which are marked as “content”. So if your build-script is based on MSBuild you could leverage this task to copy all files for your web-application to a certain destination.

Since I prefer NAnt over MSBuild I was looking for a solution to accomplish the same with NAnt. So I found a post of Petter Wigle. He has a great approach of creating a NAnt file on the fly by analyzing the web-application’s project-file.

Basically he’s applying a XSLT script to create a fileset-definition of all files that need to be copied. This script can then be called during the build-process.

Categories: Programming Tags:

December 2009 Cumulative Update Packages for SharePoint Server 2007 und Windows SharePoint Services 3.0

February 5th, 2010 No comments

On January 29th 2010 the December Cumulative-Update for WSS and MOSS has been released.

The Changes for WSS can be found in

  • 977022 (http://support.microsoft.com/kb/977022/ ) Description of the Windows SharePoint Services 3.0 Cumulative Update Server Hotfix Package (Sts-x-none.msp): December 15, 2009
  • 977731 (http://support.microsoft.com/kb/977731/ )Description of the Windows SharePoint Services 3.0 hotfix package (Sts-x-none.msp, Wssmui-en-us.msp): December 15, 2009
  • 977732 (http://support.microsoft.com/kb/977732/ ) Description of the Windows SharePoint Services 3.0 hotfix package (Wssmui-en-us.msp): December 15, 2009

and the changes for MOSS

  • 977023 (http://support.microsoft.com/kb/977023/ ) Description of the Office SharePoint Server 2007 Cumulative Update Server hotfix package (Coreserver-x-none.msp): December 15, 2009
  • 977024 (http://support.microsoft.com/kb/977024/ ) Description of the Office SharePoint Server 2007 hotfix package (Dlc-x-none.msp): December 15, 2009
  • 977028 (http://support.microsoft.com/kb/977028/ ) Description of the Office Project Server 2007 hotfix package (Pjsrvapp-x-none.msp, Pjsrvwfe-x-none.msp): December 15, 2009

Seems like I need to create a new Slipstream-Setup.

Categories: SharePoint Tags:

Need some IIS stuff?

February 5th, 2010 No comments

I just stumpled across the offical Microsoft IIS Site, which I didn’t actually knew so far. This is a great resource for IIS, especially if your looking for security or performance related addons for IIS.

Categories: IIS Tags:

Slipstream for SharePoint

February 4th, 2010 No comments

Just in case you’re in the need to install SharePoint and you want to incorporate the latest updates into your install – there is a better way than installing SharePoint and then start wssv3sp2-kb953338-x86-fullfile-en-us.exe and officeserver2007sp2-kb953334-x86-fullfile-en-us.exe.

Using a slipstreamed install you can install all updates during the initial installation, thus saving you a lot of time you would have spend to install the updates otherwise.

  1. Copy the SharePoint installation CD onto a network share
  2. Download of SP2 for Windows SharePoint Services as well as Office SharePoint Server
  3. Extract SP2 for Windows SharePoint Services using the /extract switch to the Updates folder within the install-folder of the SharePoint CD (wssv3sp2-kb953338-x86-fullfile-en-us.exe /extract:[path to install-folder\Updates]).
  4. Extract SP2 for Office SharePoint Server using the /extract switch to the Updates folder within the install-folder of the SharePoint CD (officeserver2007sp2-kb953334-x86-fullfile-en-us.exe /extract:[path to install-folder\Updates]).
  5. Delete wsssetup.dll from the Updates folder, because this migth cause a conflict with svrsetup.dll.

The same way applies to cumulative updates. Important is to keep the chronological order of the updates (oldest first!) as well as to first apply WSS updates before MOSS updates. So you should first integrate the December CU for WSS and then the December CU for MOSS.

This can even be applied to Language-Packs.

  1. Download of the needed Language-Pack.
  2. Extract the Language-Pack using the /extract switch.
  3. Download of Language-Pack updates.
  4. Extract the Language-Pack updates using the /extract switch.
  5. Copy the extracted files from step 4 to the Updates folder within the extracted files of step 2.
Categories: SharePoint Tags:

Lorem Ipsum

January 27th, 2010 No comments

Once in a while you need to fill in some dummy-text. Usually this is done, by leveraging the “lorem ipsum” text.

While there are a couple of websites, that can create this text (like http://www.lipsum.com/), this is actually unnecessary while working with Micorsoft Word 2007. Just type in =lorem(10,5) and you’ll get about 10 paragraphs with up to 5 lines of text per paragraph.

This is kinda neat.

Categories: General Tags: ,

Painless filtering in NHibernate

January 20th, 2010 No comments

The Stage

Let’s assume, there exists an application, which is already heavily relying on NHibernate. This app is supposed to be extended. All wordings are currently available in a single locale and re stored in the database. This is matter to change, since we want to introduce multi-language capabilities for our wordings.

The Plan

The simplest way to achieve the requirement would be to extend the domain-model in such a way, that a new column would be added to the tables in the database. This column would contain the locale of the text. Instead of a single row for each text, we would end up with a single row for each locale for each text.

In order to retrieve a certain text from the wording-table of the database, we not only need to know which text to get, but we also need to know which local of the text we need to get. So this would end up in an additional criteria when retrieving data from the database. This is the point where NHibernates comes into play. NHibernate offers global filters, which can be used in conjunction with regular queries.

I will demonstrate how to make use of these filter by showing a little example.

The Implementation

Let’s take a small app, which is persisting pizza and toppings using NHibernate. Therefore we have POCOs and according mappings.

namespace Pizza.Entities
{
    /// <summary>
    /// Business Entity representing a pizza-topping
    /// </summary>
    public class Topping
    {
        /// <summary>
        /// The internal, unique id of this topping
        /// </summary>
        /// <value>The id.</value>
        public virtual int Id { get; set; }

        /// <summary>
        /// the name of the topping
        /// </summary>
        /// <value>The name.</value>
        public virtual string Name { get; set; }
    }

    /// <summary>
    /// Business Entity representing a pizza
    /// </summary>
    public class Pizza
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Pizza"/> class
        /// </summary>
        public Pizza()
        {
            Toppings = new List<Topping>();
        }

        /// <summary>
        /// The internal, unique id of this pizza
        /// </summary>
        /// <value>The id.</value>
        public virtual int Id { get; set; }

        /// <summary>
        /// the name of the pizza
        /// </summary>
        public virtual string Name { get; set; }

        /// <summary>
        /// the toppings, which are being used by the pizza
        /// </summary>
        public virtual IList<Topping> Toppings { get; private set; }
    }
}
<class name="Topping" table="Toppings">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name"/>
</class>

<class name="Pizza" table="Pizzas">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name"/>

  <list name="Toppings" table="PizzaToppings" cascade="all">
    <key column="PizzaId" />
    <index column="Position"/>
    <many-to-many column="ToppingId" class="Topping" />
  </list>
</class>

As you can see, pizza as well as toppings each have a name. A pizza also has a set of toppings.

So far, so good. To support multiple locales we could go several ways. We could introduces a property called Name_de as well as Name_en to support german (DE) and englisch (EN) locales. An alternative approach would be, to add a property called Locale, which hold the locale of the name. If I would like to get english pizzas I would need to filter for pizza entities, which have a locale of “en”.

OK, let’s go with the second alternative. But how do I restrict my queries to only fetch pizza entities with locale=en? With NHibernate-Filter!

First of all we need to define a filter.

<filter-def name="localized">
  <filter-param name="myLocale" type="System.String"/>
</filter-def>

The next step is, to include this newly created filter in the mappings.

<class name="Topping" table="Toppings">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name"/>
  <property name="Locale"/>
  <filter name="localized" condition=":myLocale = Locale"/>
</class>

<class name="Pizza" table="Pizzas">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name"/>
  <property name="Locale"/>

  <list name="Toppings" table="PizzaToppings" cascade="all">
    <key column="PizzaId" />
    <index column="Position"/>
    <many-to-many column="ToppingId" class="Topping">
      <filter name="localized" condition=":myLocale = Locale"/>
    </many-to-many>
  </list>
  <filter name="localized" condition=":myLocale = Locale"/>
</class>

This way I specify that by using the filter I want to restrict my results by the column Locale. It’s important to notice, that this will only happen when I’m actually using this filter. When I’m not using the filter this restriction is being ignored. Thus: the filter is optional!

OK, so how does this actually work in my application – how do I use such a filter? What I don’t want: I don’t want to change all my existing queries to include a filter for the locale column. Instead I’m just activating the previously defined filter and assign a certain value.

// enable the filter
_session.EnableFilter("localized").SetParameter("myLocale", "de");

// do some plain ol’ querying
var pizzaList = _session.CreateCriteria<Entities.Pizza>().List<Entities.Pizza>();

That’s it. There is nothing more to it. I can leave all my queries the way they are and just execute them like before. Let’s take a look at the SQL statements that are being created, because they will show the usage of the filter.

SELECT this_.Id as Id2_0_, this_.Name as Name2_0_, this_.Locale as Locale2_0_
    FROM Pizzas this_
    WHERE @p0 = this_.Locale;@p0 = 'de'

This shows the strength of NHibernate-Filters. Besides the modification of the mappings and the activation of the filter I don’t need to modify anything. I don’t need to alter my queries. The filter is being applied by NHibernate behind the scenes.

This also works in more complex scenarios. Let’s assume I have a pizza with several toppings. I only want to get a pizza in german – and of course I also want to get german toppings as well. This works as too.

var multiPizza = new Entities.Pizza {Name = "Multikulti", Locale = "de"};
multiPizza.Toppings.Add(new Topping {Name = "Käse", Locale = "de"});
multiPizza.Toppings.Add(new Topping {Name = "Mushrooms", Locale = "en"});
_session.Save(multiPizza);

_session.Flush();
_session.Clear();

var fromDb = _session.CreateCriteria<Entities.Pizza>().Add(Expression.Eq("Id", multiPizza.Id)).List<Entities.Pizza>()[0];

Assert.That(fromDb.Locale, Is.EqualTo("de"),"pizza locale");
Assert.That(fromDb.Toppings,Has.Count.EqualTo(1));
foreach (var topping in fromDb.Toppings)
{
    Assert.That(topping.Locale, Is.EqualTo("de"),"topping locale");
}

I already activated and set the filter in the constructor of my class – so I don’t need to do this over again. At least not as long as I reuse the same session. Let’s take a look at the SQL send tot eh database – this is just impressive!

SELECT this_.Id as Id2_0_, this_.Name as Name2_0_, this_.Locale as Locale2_0_
    FROM Pizzas this_
    WHERE @p0 = this_.Locale
        AND this_.Id = @p1;@p0 = 'de', @p1 = 4

SELECT toppings0_.PizzaId as PizzaId1_, toppings0_.ToppingId as ToppingId1_, toppings0_.Position as Position1_, topping1_.Id as Id1_0_, topping1_.Name as Name1_0_, topping1_.Locale as Locale1_0_
    FROM PizzaToppings toppings0_ left outer join Toppings topping1_ on
        toppings0_.ToppingId=topping1_.Id
    WHERE  @p0 = topping1_.Locale
        and toppings0_.PizzaId=@p1;@p0 = 'de', @p1 = 4

Conclusion

The use of NHibernate-Filters introduces a very transparent way to extend the applicationlogic to include additional filter criteria.

  • Instead of storing a newly localized text in a seperate column, this doesn’t require any schema-changes.
  • Only the rows to a certain locale are being retrieved, this might reduced bandwith.
Categories: .Net Tags:

Where’s that data?

January 18th, 2010 No comments

ASP.Net applications have a special folder call App_Data, which is specifically designed to hold application-data such as databases. SQL-Server express will place it’s .mdf files here by default.

Because this directory is being protected by the .Net-framework and thus not accessible by clients, it’s a good idea to place other data here as well.

To access this folder a couple of different approaches come to mind. The first idea would be to just access /App_Data/mydata.db hardcoded. While this might work in most scenarios, it will fail if the application is installed in a virtual directory instead of the root.

OK, let’s try something different. How about ~/App_Data/mydata.db? Looks compelling. At runtime the .Net-framework will substitute “~” with the actual base-directory of the application. Unfortunately this is only done for certain elements. So this might not always work. You could of course get the actual path on the server side by using

Server.MapPath("~/App_Data/mydata.db");

Doing some research offers my preferred approach

Path.Combine(AppDomain.CurrentDomain.GetData("DataDirectory").ToString(), "mydata.db");

AppDomain.CurrentDomain.GetData("DataDirectory") will return the path to the App_Data folder wherever that’s actually may be. Nice.

Categories: .Net Tags: