Tuesday, December 15, 2009

Blackberry sync on Mac - thank god for gmail contacts

I tried to sync my blackberry contacts with my Mac address book contacts today using the not so long ago released software for this, and I have to say that RIM has some work to do here yet. Thankfully I have my contacts stored in my gmail account cause the sync made a mess and a half of my blackberry AND my mac address book. I can understand that this isn't the easiest thing to get right, but when my email fields say SMTP instead of the actual email address for many contacts, I think the software is unusable. Data loss in this type of application is not acceptable. I'm sure there is some perfectly logical explanation of how this happened, but sorry guys, I am just an end user and I was just running your software. Let's just say that this is a great way to motivate Mac users to buy an iPhone instead of a Blackberry when the next upgrade moment comes. Hope you can fix it before then.

Now back to fixing my address book, I am at 'J' and have been at it for a while now.........

Thursday, November 05, 2009

new xcomplica.com

A few days ago I launched a new version of xcomplica.com . My friend Alex at Wars van Peoha (Alex now has a new company - Green Creatives )made a great design for me to start from and I am proud to say that I did the rest myself. The html, css and jQuery bits took me the longest since I am no expert in these while the ASP.NET MVC back end was a breeze.

This is the first step in my plan to grow XComplica past the one man show that it now is. Other steps are underway, stay tuned.

Thursday, October 29, 2009

Don't be evil, right?

Yesterday and today I felt first hand how giant Google has become and the negative effects it has on the world. I now see that while the stuff coming out of the Googleplex is often very cool, Google is in some ways becoming the Wallmart of the internet. As soon as they show up, everyone else is expected to go broke. What do I mean by that? Well online there aren't physical locations that companies compete in, but there are product spaces. And as soon as Google enters a product space, any companies active therein are suddenly second class citizens expected to be overtaken by the giant Google. So while the Google product may even be inferior, just the Google brand gives it the edge.

How did I see this? I own shares in a Dutch company called Tom Tom that is one of the market leaders in navigation systems. Yesterday Google announced their entry into this market, and shares of Tom Tom as well as others in the market plummeted. I am of course not happy about the financial outcome for me. More importantly however, I am starting to see that the sheer size and reputation of Google is going to make it impossible for them to stand by their "Don't be evil" philosophy.

Wednesday, September 16, 2009

Working on MAC

I have been working on my Macbook Pro for a few weeks now and have to say I have been quite happy with it. The hardware is great and I have found OS X to have everything I need for my daily tasks. I do miss having Visual Studio and MS Office on my local machine, but I have a virtual machine using Parallels that I use for this software. Parallels has been working quite well, I just can't get the automatic snapshot thing to work. It took an automatic snapshot once, and since then has been ignoring the schedule I gave it.

The only downside that I have found on the Mac compared to my Thinkpad is that the Macbook is not as tough. I have unintentionally put both of them through the same drop test and the Thinkpad fared much better. Both times I dropped the machine in question a half meter onto the floor. The Thinkpad had a little cosmetic damage on the battery, which can be replaced quite inexpensively. The Macbook has a nasty dent on the bottom right corner, and I don't think I will be trying to hammer it out anytime soon. I have yet to talk to Apple to see what the repair would cost but I have a feeling replacing the unibody will not be so cheap. Luckily both machines work just fine, which is more than I would expect from many other notebooks if I put them through this test. I guess I have now "personalized" my Macbook and will have to live with the dent. I do feel like a tool for doing this to my computer right after I bought it. I just hope my warranty will still be valid.

Wednesday, September 02, 2009

Code snippet for Visual Studio for creating site columns

I have created a code snippet file which I use to create site columns in CAML. It is by no means perfect or complete but I find it useful so someone else might too. How to use code snippets is explained in many places so I won't regurgitate that here. I will mention that you need to type the open angle bracket, hit ESC to disable intellisense and then type the site column shortcut followed by TAB.

Get the snippet file here http://www.xcomplica.com/downloads/sitecolumns.snippet.txt and remember to remove the txt extension.

Friday, August 21, 2009

Screwed by sky europe

Gotta love the 5 hour delay on a 2 hour flight, and the sudden change of destination. Thanks sky europe, never flying you again. I guess I'm not alone though seeing as you're going bankrupt.

UPDATE: Screwed a second time when they really did go bankrupt and I had to buy a new flight home from vacation.
---

Friday, August 14, 2009

New Site

Not too long ago I finished working on a new site and forgot to blog about it. The site is American Express Avenue and was created in ASP.NET MVC 1.o. I had a great time learning MVC, LINQ to SQL and a few other things and am hoping this stuff will show up in the next version of MOSS.

I am a Mac

The last few months have seen my trusty T43p Thinkpad slow down and demand retirement. I have to say it was by far the best machine I have ever owned and it was my only computer for the first three years of my business. Sincere thanks to IBM.

I thus decided to buy a replacement, and after much deliberation (ask people who I worked with recently) I decided to buy a MacBook Pro. I bought the flagship 17 inch with almost all the upgrades (didn't shell out the extra grand for 8GB of RAM).

So far I am quite pleased with it. I am sticking with the pre-installed OS since it seems to be working quite well on the machine, and have managed to switch to the Mac world without too many issues. The only big one was that VMWare Fusion froze twice on me and killed two VPCs in the process. Two days of work gone == I am now using parallels. I am just about to embark on a new MOSS project and am curious how well this new setup will work. More in a few months.

Wednesday, May 13, 2009

Is blogging not cool anymore?

A few years ago, blogging became the latest rage.  Everyone and their grandmother had a blog and was contributing dutifully to spewing random brain trash onto the internet.  I recenlty noticed how many of these blogs have died out or whithered away.  It would be interesting to see the number of unique blog posts worldwide per month, to see if my personal experience actually matches reality.

There is still plenty of trash being spewed out onto the internet, but it has moved on to other services.  Thanks twitter. 

Friday, May 08, 2009

Does this link work for you?

Today I was trying to activate support incidents for a client's MSDN subscription.  I called Microsoft as their web page on MSDN suggested, and they told me I need to fill out a form, and email it back to them.  Ok, no problem.  They then told me the url where I could get the form.  I typed it in and got an error.  Weird, perhaps I can't type.  So after a few attmepts at spelling it out on the phone, the MS guy emailed me the link.  Still no go.  At this point I was transfered to another department who told me to go to the same link.  They tried to tell me that I may be using the wrong version of IE (I have IE7) or that my proxy server may be messing things up (no proxy server).  In any case, I must be the moron because I got the "It works over here" response from them.  

At this point, I want to know if anyone can actually see this link. 

[UPDATE: I just tried this from home, still no go.]

[UPDATE 2: It works now.  The trick as pointed out by Syd was that I had my country settings set to US.  I do this so that I don't have to read all the MS pages in Dutch.  Well it turns out that once I changed my country settins to the Netherlands, the url works.  Thanks Syd.]

As emailed from MS:

------------------------------------------

Dear Joe,

 As promised I send you the URL to activate the support for your MSDN subscription:

http://support.microsoft.com/activatesupport

 Kind regards,

Microsoft B.V.

Tuesday, April 14, 2009

A new experience

I had a new experience today, a not so pleasant one.  I got rear-ended by a taxi while on my motorcycle. Legally it was all his fault, but I am still pissed at myself for not seeing it.  I'll have to be more critical of myself in the future about road position, etc.  

Luckily I was not hurt, and the bike only had some cosmetic damage.  I was able to ride it to the dealer and it should be back on the road in a day or two.  In the meantime I am on a Suzuki V-Storm, not a bad bike from my impression so far.

Wednesday, April 08, 2009

A great tool

A quick note about a great free tool that I used on my last project to figure out what was really going on with my http traffic.  The tool can do a lot more than that too:



Multiple authentication providers and SSO into MOSS

Recently I faced a problem where I had to enable a MOSS site to be accessible using three different methods. One was the standard windows authentication, the second was Forms authentication and the third was a SSO method where a user identification token came in the querysting.

Getting the first two up and running is documented in many places so I will not repeat that here. See these links for instance:

http://blogs.msdn.com/sharepoint/archive/2006/08/16/configuring-multiple-authentication-providers-for-sharepoint-2007.aspx

http://www.andrewconnell.com/blog/articles/HowToConfigPublishingSiteWithDualAuthProvidersAndAnonAccess.aspx


What was new for me was the third requirement. The specifics were that the querystring would contain a user token which could then be used to call a web service to authenticate the user. The user would not notice any of this and be logged in automatically. This method was used so that users coming from another portal could enjoy a Single Sign On experience when going to the MOSS site.

I solved this as follows:

  1. I extended the web site to yet another URL.
  2. I changed the login page (in the web.config of the newly extended web app) to a custom login page.  * More on this later
  3. I added another membership provider line in the web.config of all the web applications corresponding to this site (Windows Integrated, Forms, SSO) which was the same as my forms membership provider except for two things:
    • The name of the provider has to be different
    • The applicationName is different
    This ensures that any users created to work with the SSO site will not be available for the forms site, while I can still use the database created for the Forms authentication provider. 
  4. I added a new role provider that is again the same as the role provider for Forms, just with a different name.  (This I did since MOSS does not allow you to use the same membership or role provider for different zones)
  5. I then went to central admin and changed the authentication type of the zone corresponding to the SSO web app to forms.  I specified the new authentication and role providers.  Even though the authentication type is forms, the user never gets a chance to enter a username or password due to the code in the login page. 
* This login page has logic in it to call a web service which accepts the token and returns the user name (if token is valid). It then uses the standard memership methods to authenticate the user based on the returned username and a static password that is the same for each user. These users are stored in the same database as the Forms users but with a different application name so that they can only be used from the SSO site.

I had also created some tools for user management that I then updated to be aware of multiple membership providers.  For example, my web part that created a new users has a radio button choice in it that forces the choice of a Forms user or an SSO user.  This drives which provider is used to create the user.  Similar logic is used in user editing, listing, etc.  

There are a number of alternatives to this solution such as creating a new user database for the SSO membership provider or even creating a new membership provider, however I found this technique to be the least amount of work and quite effective. 

Monday, February 09, 2009

Handy Hiding Panel

Often in SharePoint (Although this could be used elsewhere) I have a need to hide something from some users or in case of some situation. For instance I may want to hide a set of controls if the MOSS site is accessed from a specific URL (like the internet facing site).

In these cases I use a control I call the hiding panel. It is quite simple but so handy that I find it useful to blog about. The code first:

using System.Web.UI.WebControls;
using System.Web;
using System.Web.UI;

namespace JoeDemo
{
public abstract class HidingPanel : Panel
{
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
if (GetCondition())
{
base.Render(writer);
}
}

protected abstract bool GetCondition();
}

[ToolboxData("<{0}: PublicUrlPanel runat=\"server\"></{0}: PublicUrlPanel>")]
public class PublicUrlPanel: HidingPanel
{
protected override bool GetCondition()
{
return HttpContext.Current.Request.Url.Host.ToLower() == "public";
}
}
}


I define an abstract class that is the generic hiding panel - it only renders when the condition is true. I then can have many classes that inherit from the Hiding panel, each implementing their own version of the GetCondition method.

The example here has the Public url panel which only displays if the host portion of the url is 'public'. Mind you this is not the best production code, the string shoudl not be baked in here but that's not the point here.

To use this, you simply add the panel to your page layout (or ASPX page if not in MOSS) and use the same way as a panel:

<myControls:PublicUrlPanel id="myPanel" runat="server">
<asp:Literal id="testLit" runat="server" Text="Accessed from public url"/>
</myControls:PublicUrlPanel>


Note that in SharePoint designer you should just be able to drag and drop this panel from the Server Controls list in the toolbox. If you are adding the code manually, you also need to register your assembly somewhere on the page with a register directive like

<%@ Register TagPrefix="myControls" Namespace="JoeDemo" Assembly="JoeDemo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=aaaaaaaaaa"%>


UPDATE: Today I was working with this code and realized that when the Panel renders, it can throw off the look of your web page due to its rendering of a DIV tag. To get around this, I simply stopped using a Panel control and switched to a PlaceHolder control. Cleaner rendering and no loss in functionality.

Thursday, January 29, 2009

Nice tool for blogging source code

I was struggling with formatting the source code for my blog today and found this handy tool FORMAT MY SOURCE CODE FOR BLOGGING

Thanks Greg!

Using ASCX in WebParts and UserControls in SharePoint

I was explaining my technique of using User Controls in MOSS to someone today and they said I should blog about it. I figured there would be many people who have but a quick Google search didn't reveal as many results as I thought. So here goes:

In order to get around the issue of not being able to have pages with code behind in them, I have been using User Controls. Over the years I have adopted one way of developing web parts and user controls for which the code lives in DLLs but the layout still exists in ascx files. This may not be the only or best way to accomplish this but it is a way that has always worked for me.

On many of my assignments I receive HTML from a web designer and my job is to implement the functionality. I like working this way. As long as I ensure that the HTML my code ends up rendering is the same as the HTML the designer delivered in her static page, I know the page will look great. This means I usually start by taking the HTML and translating it into ASP controls.

So for example I may receive the following snippet from the designer:

<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>


I know that item 1 and item 2 are just an example, and the values here will need to dynamically come from a SharePoint list for instance. So I translate this to a repeater (my favourite ASP.NET cotnrol):

<asp:Repeater ID="MyRepeater" runat="server">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><asp:Literal ID="litItemValue" runat="server"></asp:Literal></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>


This way I know that the rendered HTML will be exactly what the designer intended and thus the page rendering will not be broken.

Now that I have the ascx ready, I want to use it in a user control or a web part. My next step then is to create a class in a Class library and have this class dynamically load the ascx into a user control object. I do this by calling the Page.LoadControl() method as seen in this code:

public class MyWebPart : WebPart
{
private const string ControlPath = "/_controltemplates/MyApplication/";

private UserControl myControl;
private Repeater myRepeater;

protected override void CreateChildControls()
{
base.CreateChildControls();

myControl = (UserControl)Page.LoadControl(ControlPath + "MyControl.ascx");
Controls.Add(myControl);

myRepeater = (Repeater)myControl.FindControl("MyRepeater");
}

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
EnsureChildControls();

myRepeater.ItemDataBound += new RepeaterItemEventHandler(myRepeater_ItemDataBound);
myRepeater.DataSource = GetData();
myRepeater.DataBind();
}

private object GetData()
{
// create a proper data source here
object myReturnValue = new object();
return myReturnValue;
}

void myRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
// do your stuff here
}
}


The Page.LoadControl is the crucial part, but there are a few other bits that I'd like to explain here.

First there is the issue of the path that the control is being loaded from. This path is a virtual directory path, and I like to use the already existing virtual directory created by MOSS called _controltemplates. Seems like the right place to put control templates. Just to keep things neat I like to have a folder here for each application. Note that this virtual directory corresponds to the physical directory {Location of 12 Hive}\TEMPLATE\CONTROLTEMPLATES on your MOSS server(s) so if you place you controls here, things will work. I like to deploy my control templates using MOSS solution files but that's another post.

The second thing to note is that you have to add the UserControl object to the this.Controls collection. If you forget this, your web part will not render anything and you may get null reference exceptions.

Third, make sure you get the ID correct when using the FindControl method. Doing the lookup based on a string ID works fine, but if you have the wrong ID in here you will not know until you get a nasty null reference exception at runtime.

Last, remember to call the EnsureChildControls() before you start using any of the controls in your template. Otherwise you may get yet another null reference exception.

To get this all finally working, build your class library, register is as safe in the web.config file and add it to the bin folder of the MOSS application or the GAC. You should then be able to use your web part or user control.

Good luck.