Archives

Archives / 2005 / September
  • [.NET 2.0] Creating your own CatalogPart

    In two earlier posts (here and here), way back in beta1, I showed how to create your own CatalogPart which could display a list of available web parts from a database or something. Some people will be quite happy to add web parts in a declarative way, but I wanted a solution which were more dynamic. In the future I'll try to write some sample code where you create web parts in a separate library and just drop them in a directory somewhere in the portal, and the web parts gets picked up automatically in the CatalogZone without the need to change the code. Just as a proof of concept.

    Anyway, I noticed that the code changed somewhat in beta2 compared to how it used to work back in beta1. There are two ways (at least) you can add your own CatalogPart to a web page:

    1. Create your own CatalogPart and declare it in the CatalogZone, in the aspx-page. This is the simplest way. See sample below.
    2. Create your own CatalogZone and declare it in the aspx-page. This CatalogZone then adds your CatalogZone declaratively or in run-time. A bit more coding and there is no need to do it this way unless you plan on doing something special within your CatalogZone. What that may be, I don't really know :)

    So, sample code for MyCatalogPart:

    using System;

    using System.Web.UI.WebControls;

    using System.Web.UI.WebControls.WebParts;

    using System.Collections;

     

    namespace MyCatalogZones

    {

          public class MyCatalogPart : CatalogPart

          {

                public override WebPartDescriptionCollection GetAvailableWebPartDescriptions()

                {

                      //Generate a list of available web parts that shows 

                      //up in the catalog, each with a unique ID

                      //This sample code just adds one web part

                      WebPartDescription wpDescription = new WebPartDescription("MyWebPartID", "My Web Part", "A description of the web part", null);

                      ArrayList arrWpDescriptions = new ArrayList();

                      arrWpDescriptions.Add(wpDescription);

                      return new WebPartDescriptionCollection(arrWpDescriptions);

                }

     

                public override WebPart GetWebPart(WebPartDescription description)

                {

                      //a bit of "dummy" code to add a specific web part

                      //which maps against "MyWebPartID" from the catalog

                      if (description.ID == "MyWebPartID")

                      {

                            //returning an instance of the selected web part

                            MyWebParts.MyWebPart newPart = new MyWebParts.MyWebPart("My Web Part");

                            return newPart;

                      }

                      return null;

                }

          }

    }

    Note that in the code above, when you create the list, you may want to check if the user has already added an instance of the web part to his page before you add it to the list. This depends on if you want to let the users add a web part several times to the page or not. The web part may be such that it can be configured to show different content depending on its properties, so why not...

    This is some sample code for adding your CatalogPart to a normal CatalogZone in an aspx-page:

    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

    <%@ Register TagPrefix="jd" Namespace="MyCatalogZones" Assembly="MyCatalogZones" %>

     

    <!-- lots of aspx code here... -->

     

        <asp:CatalogZone ID="CatalogZone1" runat="server" >

            <ZoneTemplate>

            <asp:DeclarativeCatalogPart ID="DeclarativeCatalogPart1" runat="server">

              <WebPartsTemplate>

                <asp:label id="aPartInTheCatalog" runat="server" title="Catalog webpart">

          <h2>Dummy part</h2>

          <p>This is a part in the catalog.</p>

        </asp:label>

              </WebPartsTemplate>

            </asp:DeclarativeCatalogPart>

            <asp:PageCatalogPart ID="PageCatalogPart1" runat="server" /> 

            <jd:MyCatalogPart ID="MyCatalogPart1" runat=server Description="My own dynamic catalog part" Title="My Special Parts Catalog" />

          </ZoneTemplate>

        </asp:CatalogZone>

     

    <!-- lots of aspx code here... -->

     

    You don't really have to have the DeclarativeCatalogPart and the PageCatalogPart there, but if you allow users to close your dynamically added parts, you may want to let them add them again, so the PageCatalogPart may be useful :)

     

  • XLINQ blows my mind

    Just spent a couple of hours setting up a couple of VPC images with all "The Goods" we got from PDC'05. Last thing I installed was the LINQ tech preview. I've just spent a few minutes looking at the LINQ samples that comes on disk 4 and I've tried a few DLINQ stuff which was really impressive, but the XLINQ features just blows my mind. The whole style of programming seems so natural compared to the old XmlDocument way of doing things. Let me copy a few lines of code from the RssAggregator sample, a method which pulls Rss from a couple of feeds, extracts the items and returns a list of all these items:

    static IEnumerable<XElement> GetItems() {

    string[] feeds = {

    "http://blogs.msdn.com/cyrusn/rss.aspx",

    "http://blogs.msdn.com/mattwar/rss.aspx",

    "http://blogs.msdn.com/lucabol/rss.aspx",

    "http://www.pluralsight.com/blogs/dbox/rss.aspx",

    "http://blogs.msdn.com/jomo_fisher/rss.aspx"

    };

    foreach (var str in feeds) {

    var feed = XDocument.Load(str);

    var items = feed.Root.Element("channel").Elements("item");

    foreach (var item in items)

    yield return item;

    }

    }

    I love the way you get hold of a specific element in the document with Element("nodename"). Not sure I'm comfortable with the "var" thing though. That's the "implicitly typed local variables" that comes with C# 3.0. I guess it's the way I read code. If you want to read about the new features in C# 3.0, you can download the spec from here.

  • Trying to install Windows Vista on VPC

    As everyone else on the PDC, I got a PDC-version of Windows Vista. I tried to install in on a VPC yesterday, but I never got past the install step where you have to specify on what disk to install to. I tried (within VPC) to delete the virtual partition and format it, but it never got available. I wonder if anyone else experienced the same problem...
  • [PDC'05] Last day at the conference

    Best session yesterday was probably the web services interop session with Simon Guest and Kirill Gavrylyuk. To show reliable messages between .NET and Java, Simon hocked up a heart beat sensor (which sat on his finger) onto a .NET web service. Then he sent data from that sensor over to a Java client, through a pre release of Axis 2.0. Funny (for the audience anyway) was that Simon heart was pounding so rapidly, the scale on the client couldn't handle it. They had set it up to a maximum of 100 bpm, but he was going at around 130 (!) and the annoying beep-beep-beep that was going on all the time didn't make it easier for Simon to calm down. It was hillariously fun. Make sure to watch that webcast if it comes available sometime in the future.

    They showed how to send and receive WS-Security messages as well as Reliable Messages and how to send binary data with MTOM. MTOM stands for Message Transmission Optimization Mechanism.

    Later in the evening I sat down and had a discussion with Kirill about the WS design we have in the project I'm working with back home. We seem to be on track, but there are a few things I could change on the architecture to be a bit better prepared and in line with the future. Should perhaps start looking at sending SAML tokens instead of just a simple proprietary ticket.

    I spent the whole morning (2 sessions in a row) at the Architecture Symposium here, where they discussed a fictionarly SOA case from end to end. It was quite interesting, but the reality isn't always as Microsoft describes it. Setting up Aggregation Services and Entity Services in front of one or more legacy system is the recommended design if you have a heterogenous environment. Maybe stick in BizTalk or similar workflow middlewhere with adapters if you think you need it to talk to bigger systems like SAP, PeopleSoft and such.

    After this last session I'm going to now, it's off to the LAX airport for the lovely trip home...

  • [PDC'05] Did some coding with "indigo"

    Or WCF (Windows Communication Foundation) as it is now called, and it is very, very powerful. I sat down in the lab area where they have everything you need installed, complete with lab instructions, and tried out a few web services and such. Support for contract first coding is better now, where you first create the "contract" as an interface and you then go on and implement this contract with code. You can do the same sort of things on the client. I like that.

    I also had a quick look at the LINQ stuff, and it's pretty cool coding. LINQ style coding will probably replace the ADO.NET code you do in your Data Access Layer if you use such an architecture. It is powerful and intuitive and there is no longer a need for a mapper design pattern where you map a strongly typed data set (or similar datatable object) into a DTO (Data Transfer Object), because you can create the DTOs directly with LINQ. In ADO.NET 2.0 you can continue using the same kind of code and patterns you used in .NET 1.1, but I would suggest everyone to look at the ObjectDataSource stuff and

    Something I would like to look at in more detail is the workflow foundation, but that will have to wait until I get home.

  • [PDC'05] ”I think I may need a bathroom break. Is this possible?”

    Lol, maybe they had as much free coke, coffee, juice and ice cream at the top meeting Mr Bush was attending as we have here at the PDC'05 convention, but if that was the case I understand him. If not, it's another great quote in the never endling list of quotes the most powerful guy in the world has produced, this one in writing... :)

    Anyway, it feels encouraging that he actually can write and that he has normal human needs... there is hope for the world after all. ;)

  • [PDC'05] Impressions from yesterday

    Yesterday was the best day so far at the PDC. Most impressive things was first what will probably become 'ADO.NET 3.0' or something similar - LinkQ or DLinkQ, which is dynamic language integration (or something like that). Eric blogged about that. Next thing which was really, really cool and got lots of applause from the session attendees was the new integrated workflow foundation, which is basically a powerful workflow engine. The Windows Worflow Foundation is a part of the WinFX subsystem and will let you host workflows in lots of different containers, like IIS, a windows forms app, sharepoint, SQL server or even in a console app! It's also dead simple to use. It's as if you ripped out the basic workflow engine from Biz Talk and created a powerful set of APIs to use against it. It will be used ALOT in the future. The graphical workflow designer in Visual Studio was impressive.

    Last night was Universal Studio Theme Park night and it was just great! Me and my friends rushed off to the Jurassic Park and The Mummy rides as fast as we could to get a head of all the other 8000 or so people there. Really cool rides I must say :) If you ever go to Los Angeles, don't miss it. We tried most of the rides in the park, but I think Jurassic and Back to the Future was the best :)

    Off to the next general session now.... *running*

  • [PDC'05] Blogging on Windows Vista

    Just had a great breakfast. Amazingly large selection of weird cereals. We all laughed when my buddy Jan-Erik opened his "TRIX - Fruity Sweetened Corn Puffs!" pack. Looked more like a box of candy than breakfast cereal to me :)

    Atm I'm standing in the Windows Vista Internet Alley, where they have set up hundreds of machines running Windows Vista (build 5219). The user experience is just great, lots of animations and stuff. In the future when coding for the WinFX platform I think you have to be a bit careful to not just add all of these moving and zooming stuff just because it is easy to do it. But it is cool, I must admit. Everything got a kind of soft touch to it. I wonder what kind of graphics hardware you need to run Vista graphics in optimal speed. No wonder ATI is platinum sponsor of the PDC event :D

    One of the things that drew the longest run of applause was probably when Jim Allchin (I think it was) jacked a standard USB memory into the Vista box and it got recognized as internal memory! Time to dig out all my stray USB memory sticks and get them to use, my laptop will look like a christmas tree, USB mems sticking out in every socket ;)

    Off to the next general session now with Eric Rudder and Steven Sinofsky.

    One thing I just noticed what that the rich text editor in .Text doesn't load up in IE 7

  • [PDC'05] Off to meet some other Swedes...

    Shorty we're off to meet with some of the other 100 or so Swedes that are here at the PDC. Microsoft SE has arranged for a get-togeather at a hotel close by. Will be fun to meet a few old friends that I know should be there tonight.

    Tomorrow I'll attend sessions about "Avalon" (now called the Windows Presentation Foundation), another (hopefully better) session about "Indigo" and 2 sessions about CRM solutions and "Atlas". Atlas is functionality for more easily doing AJAX-style programming in ASP.NET 2.0 and later. Looking forward to tomorrow.

  • [PDC'05] .NET "providers" is really interesting

    The concept of pluggable providers in .NET is really interesting and something I want to have a deeper look at when I get back home. The last session I was at today was about providers and how you could (quite easily) replace someting like the default membership and roles provider with your own.

    Stefan Schackow did a very good presentation about providers, which sort of saved the afternoon. I attended the COM202 session about "A lap around the Windows Communications Foundation" and it wasn't very good at all. The speaker jumped right into all the nitty gritty details you could play with in WCF and I bet 80% of the guys in there listening didn't follow him at all.

  • [PDC'05] Hurry, hurry

    The keynote with Bill G and all the others was looooong, and they ran 25 minutes over time so we had to run to grab lunch and in 10 minutes I have to be at the "Indigo" session.

    The keynotes were pretty good, Bill showed a funny video and they demoed a bunch of stuff - some more interesting and impressive than others. Highlight was when 4 of the top MS architects were at the stage at the same time, doing a combined coding demo - Don, Chris An, Anders and Steve Guthrie. That was neat. When I get back to work I'll try to demo a few of the cool things with Windows Vista and the built in RSS-capabilities you there and within Office 12.

    Time to run to the next session!

  • [PDC'05] Switched to another session

    So, originally I had planned to attend the SOA pre-conf session today, but I had a look at the material and realized I've been through most of that already and much of it was pretty basic. So I decided to change to the session about building reusable libraries with Brad Abrams. But again, that session was also pretty basic, and I've been doing coding guidelines for quite some time at work, so it wasn't that much new stuff to me. So again (right after the power failure) I decided to change session - so at the moment I'm sitting at the ASP.NET 2.0 session, where they are talking about new features in ASP.NET.

    So far so good. They've been covering Master pages, Themes and some of the controls like the menues and those. Right now it's about the Gridview and different datasources. It's cool, but I still get chills by all this declarative coding... ;)

  • [PDC'05] And all went black...

    If you've been in the "Big Hall" in the LA Convention Center, you know it IS pretty big. Imagine how dark it gets in there when there is a black out :) I was standing there writing a blog post when everything when black and silent. Power was out for almost an hour, then all started up well and sessions started again with some delay.

  • [PDC'05] Hollywood Boulevard

    So, last night we took the metro up to Hollywood Boulevard and took a walk and a big, fat hamburger. Pretty cool to see the hand- and footprints outside the Chineese Theatre and all the stars on the boulevard. Parts of Hollywood Boulevard is actually pretty run down, I was surprised to see that. The metro works pretty well, except that you had to wait pretty long before a train came along.

    Tonight we will probably walk up to Broadway and just look around.

  • [PDC'05] Pretty good start

    So, the pre-conference session (Building .NET Web Services Today with .NET 2.0 and WSE 3.0)  with Aaron Skonnard just ended, and it was pretty good. It didn't contain so much new stuff or wasn't as deep level as I thought it was going to be, but Aaron is a good speaker and I learned a couple of new things about WSE 3.0.

    Aaron spent almost 2/3 of the day on basic WS stuff that I think most people in the room might already know about, but these are pre-conf sessions so I guess they have to be a bit basic.

    Aaron did lots of coding (yay) and one funny thing was when he was going to create a demo with a web service returning datasets (which he claimed was evil). First he named the web service class 'dataset', then realized that it wasn't a very good name, so he changed it into 'webservice' which isn't that much better :) He just laughed and put a '1' after it and went ahead.

    Now we're off to see some parts of Hollywood I think...

  • [PDC'05] Cute little 9 guy

    Oh, forgot to mention that there was a soft little 9 guy in the bag too :) Like this one:

    Maybe I can put it next to my display and use it as a 'display-brick' when I get mad at something. I usually throw away CDs and DVDs, and they break so easily...

     

  • [PDC'05] Just arrived at the conference center

    Just checked in at the conference center and got my stuff: a bag (not a rucksack this time) which looks pretty good, a pretty simple gray kind of t-shirt with the PDC 'logo' on it and some magazines and stuff. Seems we have to wear these plastic bracelets (nice purple color) for the pre-conference sessions.

    The WLAN seems to working OK, just got connected with my PocketPC at once. Right now I'm standing in the big hall where they got thousands of PC hocked up to the Net, waiting for breakfast being served. I'm hungry!!

    The trip to LA took something like 18 hour all and all. I got up at 4am in Sweden, switched plane in Frankfurt, Germany (2 hours flight) and landed some 11 hours later in LA. Staying at the LA Sheraton Downtown on the 16th floor. The room is large and pretty good. I managed to stay awake til 7 or 8 in the evening before I passed out. Woke up really early, around, and at 6 my wife called :)

    Going to spend the day at the Web Services pre-conference session (Building .NET Web Services Today with .NET 2.0 and WSE 3.0)  with Aaron Skonnard. It's be interesting and great fun I hope. Write about that later.

  • Writing to Oracle CLOB fields using System.Data.OracleClient - shoot me down please

    If you're a .NET coder and does database stuff against Oracle, this is your chance to put things right :) Keep reading and add comments please!

    In one of our current projects we need to write large chunks of text to an Oracle CLOB field from an ASP.NET 1.1 application. We've been using the standard Microsoft System.Data.OracleClient libraries so far (to write smaller amounts of data) and it has worked out quite well for us. I didn't want to introduce another library pack like the Oracle ODP.NET even though the later versions of that pack may work very well.

    In older Java projects I've been writing and reading CLOBS and I know you have to handle those fields a bit different than normal VARCHARs and such. So I sat down and started to search the .NET Dynamic Help and whatever I could find on the Internet, and the funny thing is I found three different ways of doing it; 2 really simple and one not so simple. The weird thing is that I don't think the first two options is supposed to be working - but when I test them they work just fine. I'll publish the 3 ways here, and hopefully someone who knows what he's doing with .NET and Oracle can shoot me down in flames. I just want to do the right thing here.

    To test this, I have created a simple table in Oracle, which consists of 2 fields; ID (INT) and TEXT (CLOB). That's it. I'm reading a simple text-file created with Notepad, which is 499 KB in size.

    NOTE: This is just test-code, nothing you'd want to have in production. If you decide to use some of this code, please add proper error, exception and transaction handling to it.

    So, first way of doing it using an OracleDataAdapter, is (if I understand the Class Library docs) not supposed to be working. But it does:

    public void writeDataWithDA()

    {

               FileInfo fi = new FileInfo("c:/temp/testfile.txt");

               StreamReader sr = new StreamReader(fi.FullName);

               String clob = sr.ReadToEnd();

               sr.Close();

     

               OracleDataAdapter da = new OracleDataAdapter("SELECT ID, TEXT FROM CLOBTEST",ConnectionString);

               DataTable dt = new DataTable();

               // get the schema

               da.FillSchema(dt, SchemaType.Source);

     

               OracleCommandBuilder cb = new OracleCommandBuilder(da);

     

               int id = 2;

     

               // create a row containing the data

               DataRow row = dt.NewRow();

               row["ID"] = id;

               row["TEXT"] = clob;

               dt.Rows.Add(row);

     

               // update the table

               da.Update(dt);

    }

    The second way of doing it uses an OracleCommand and is also not supposed to be working (I think), but it does:

    public void writeDataWithCommand()

    {

               FileInfo fi = new FileInfo("c:/temp/testfile.txt");

               StreamReader sr = new StreamReader(fi.FullName);

               String tempBuff = sr.ReadToEnd();

               sr.Close();

              

               using(OracleConnection conn = new OracleConnection(ConnectionString))

               {

                          conn.Open();

                          Console.WriteLine("Connected...") ;

                          String strSQL = "INSERT INTO CLOBTEST (ID,TEXT) VALUES (1,:TEXT_DATA) ";

     

                          OracleParameter parmData = new OracleParameter();

                          parmData.Direction = ParameterDirection.Input;

                          parmData.OracleType = OracleType.Clob;

                          parmData.ParameterName = "TEXT_DATA";

                          parmData.Value = tempBuff;

     

                          OracleCommand cm = new OracleCommand();

                          cm.Connection = conn;

                          cm.Parameters.Add(parmData);

                          cm.CommandText = strSQL;

                          cm.ExecuteNonQuery();

     

                          conn.Close();

               }

     

               Console.WriteLine("Done!") ;

    }

    Now comes the third way of doing it. This is how the .NET Class Library documentation describes C/BLOB handling, by creating a temporary LOB object in Oracle and then write to that object before inserting in into the table. This also works fine, but it requires a bit more hassle with transactions and stuff:

    public void writeWithTempBlob()

    {

               FileInfo fi = new FileInfo("c:/temp/testfile.txt");

               StreamReader sr = new StreamReader(fi.FullName);

               String tempBuff = sr.ReadToEnd();

               sr.Close();

     

               using(OracleConnection conn = new OracleConnection(ConnectionString))

               {

                          conn.Open();

                          Console.WriteLine("Connected...") ;

                          OracleTransaction tx = conn.BeginTransaction();

     

                          OracleCommand tempcmd = conn.CreateCommand();

                          tempcmd.Transaction = tx;

                          tempcmd.CommandText = "declare xx clob; begin dbms_lob.createtemporary(xx, false, 0); :tempclob := xx; end;";

                          tempcmd.Parameters.Add(new OracleParameter("tempclob",

                                     OracleType.Clob)).Direction = ParameterDirection.Output;

                          tempcmd.ExecuteNonQuery();

     

                          //get the temp lob object

                          OracleLob tempLob = (OracleLob)tempcmd.Parameters[0].Value;

     

                          //transform into byte array

                          System.Text.Encoding enc = Encoding.Unicode;          //MUST be unicode encoded!

                          Byte[] b = enc.GetBytes(tempBuff);

     

                          tempLob.BeginBatch(OracleLobOpenMode.ReadWrite);

                          tempLob.Write(b,0,b.Length);

                          tempLob.EndBatch();

     

                          OracleCommand cmd = conn.CreateCommand();

                          cmd.Transaction = tx;

                          cmd.CommandText = "INSERT INTO CLOBTEST (ID, TEXT) VALUES (:ID, :TEXT)";

                          cmd.Parameters.Add("ID", 3);

                          cmd.Parameters.Add("TEXT", OracleType.Clob).Value = tempLob;           //insert the temp lob

                          cmd.ExecuteNonQuery();

     

                          tx.Commit();

               }

               Console.WriteLine("Done!") ;

    }

    Note that to write to the temporary CLOB, the text must be unicode or you will just get a mess of characters written :)

    So, since all three ways seems to be working just fine for me, what is the right way of doing this? Load your gun and fire away...