Contents tagged with C#

  • Custom code with SharePoint Online and Windows Azure

    Tags: .NET, C#, SharePoint, Visual Studio, Microsoft Office, Office Open XML, Windows Azure

    When I first heard about SharePoint Online at the PDC 2008 I was a bit disappointed that you could not use custom code but had to rely on the built-in functionality and the things you could do with SharePoint Designer (which is quite powerful anyway, especially with jQuery).

    To read more about SharePoint online, head over to Tobias Zimmergrens blog.

    But with some clever techniques you can take advantage of the Windows Azure Hosted Services and create your custom code. I will show you how to create some custom code, which normally is done by SharePoint event receivers or timer jobs, using a Worker Role in Windows Azure.

    The post is quite lengthy but I have skipped some of the code snippets to make it easier to read. You will find downloads of the C# code at the end of this post.

    Scenario

    This sample assumes that we have a Document Library in SharePoint Online containing Word 2007 documents for Proposals. The library is called Proposals. We want to make sure that our Proposals has all comments removed before we send it away to our clients. This comment removal procedure will be initiated by a workflow.

    The Document Library

    Action column The Proposals Document Library is a standard SharePoint Document Library with versioning enabled. First we add a new column to the library called Action. This column will contain the status of the comment removal procedure. It has the type Choice and three possible values; RemoveComments, Processing and Done.

    The workflow

    Using SharePoint Designer we create a new workflow, called Prepare Proposal. The workflow has three stages. The workflow is initiated manually

    1. SPD Workflow designerSet the Action column to the RemoveComments value
    2. Wait for Action column to get the value Done
    3. Send e-mail the the author

    Pretty simple workflow but all using the out-of-the-box SharePoint Designer activities.

    So far everything is basic SharePoint Online “development”, but now we head on over to the custom coding parts.

    Create the Hosted Service Worker Role

    Using Visual Studio 2008 and the Windows Azure SDK we can create a new project of the type Worker Cloud Service. This cloud service will contain all our code for removing the comments from our Word documents.

    Cloud Service templates

    When the project is created, actually a solution with two projects, we add two references to our Worker Role project; WindowsBase.dll and DocumentFormat.OpenXml.dll (from Open XML SDK 1.0). The Open XML reference must also have the Copy Local property set to true, so that the assembly is deployed with the hosted service App Package.

    Note: Version 2 of Open XML SDK can not be used since it does not have the AllowPartiallyTrustedCallers attribute, which is required for all referenced assemblies in Windows Azure.

    Add a service reference

    The worker role will use the SharePoint Online web services to read and update data so we need to add a Service Reference to our SharePoint online site and the Lists.asmx web service. When this is done an App.config file is created, just delete it - we have to set our bindings and endpoints in the code so it is fully trusted.

    In your worker role Start method you create code as follows:

      1: BasicHttpBinding binding = new BasicHttpBinding();
    
      2: binding.Security.Mode = BasicHttpSecurityMode.Transport;
    
      3: binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
    
      4: binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
    
      5: binding.Security.Transport.Realm = WorkerRole.Realm;
    
      6: binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;

    WorkerRole.Realm contains a string with your SharePoint Online Realm with a value something like this: “XXXXXmicrosoftonlinecom-1.sharepoint.microsoftonline.com”.

    Let’s code!

    The worker role will poll the Proposals library for new documents which has the RemoveComments value in the Action column. This is done with the GetListItems method and a query selecting only those documents.

      1: XElement query = new XElement("Query",
    
      2:     new XElement("Where",
    
      3:         new XElement("Eq",
    
      4:             new XElement("FieldRef",
    
      5:                 new XAttribute("Name", "Action")
    
      6:                 ),
    
      7:             new XElement("Value",
    
      8:                 new XAttribute("Type", "Choice"),
    
      9:                 "RemoveComments"))));
    
     10: 
    
     11: XElement queryOptions = new XElement("queryOptions");
    
     12: 
    
     13: var itemsXml = client.GetListItems("Proposals", string.Empty, query.GetXmlElement(), null, string.Empty, queryOptions.GetXmlElement(), string.Empty);
    
     14: 
    
     15: XNamespace s = "http://schemas.microsoft.com/sharepoint/soap/";
    
     16: XNamespace rs = "urn:schemas-microsoft-com:rowset";
    
     17: XNamespace z = "#RowsetSchema";
    
     18: 
    
     19: var docs = itemsXml.
    
     20:     GetXElement().
    
     21:     Descendants(z + "row").
    
     22:     Select(x => new {
    
     23:         Title = (string)x.Attribute("ows_LinkFilename"),
    
     24:         Id = (string)x.Attribute("ows_ID"),
    
     25:         Url = WorkerRole.Url + "/Proposals/" + (string)x.Attribute("ows_LinkFilename")
    
     26:     });
    
     27: 

    Now we have all our proposals in the docs variable and we can iterate over it.

      1: foreach (var doc in docs) {
    
      2:     RoleManager.WriteToLog("Information", "Processing: " + doc.Title);
    
      3:     setStatusOnDocument(client, doc.Id, "Processing");
    
      4: 
    
      5:     WebRequest request = HttpWebRequest.Create(doc.Url);
    
      6:     request.Credentials = new NetworkCredential(WorkerRole.Username, WorkerRole.Password);
    
      7: 
    
      8:     MemoryStream mems = new MemoryStream();
    
      9: 
    
     10:     using (WebResponse response = request.GetResponse()) {
    
     11:         using (Stream responseStream = response.GetResponseStream()) {
    
     12:             byte[] buffer = new byte[8192];
    
     13:             int offset = 0;
    
     14:             int count;
    
     15:             do {
    
     16:                 count = responseStream.Read(buffer, 0, 8192);
    
     17:                 offset += count;
    
     18:                 mems.Write(buffer, 0, count);
    
     19:             } while (count != 0);
    
     20:             using (WordprocessingDocument wpDoc = WordprocessingDocument.Open(mems, true)) {
    
     21:                 RemoveComments(wpDoc);
    
     22:             }
    
     23:             using (WebClient wc = new WebClient()) {
    
     24:                 wc.Credentials = new NetworkCredential(WorkerRole.Username, WorkerRole.Password);
    
     25:                 wc.UploadData(doc.Url, "PUT", mems.ToArray());
    
     26:             }
    
     27:         }
    
     28:     }
    
     29:     setStatusOnDocument(client, doc.Id, "Done");
    
     30:     RoleManager.WriteToLog("Information", "Comments removed from: " + doc.Title);
    
     31: }
    
     32: 

    First of all we have a method which updates the Action column of the item to Processing to indicate to the users that we are currently processing this document. Then we read the document into a stream and pass it into a WordprocessingDocument object. On that object we do the RemoveComments method which removes all comments in the Word 2007 document.

    Note: Have a look at Eric Whites blog for some nifty operations on your Open Xml documents, such as the remove comments function.

    When all comments are removed we upload the file back to SharePoint and set the status to Done, and we are all set.

    As you can see I use three different techniques to read from the SharePoint Online site; the SharePoint web services, request-response and a simple WebClient. Isn’t coding fun!

    Test

    One of Windows Azures beauties is that you can test it on your local machine using the Azure Development Fabric. Just hit F5 in Visual Studio.

    Development Fabric

    This allows you to debug and fine tune your code and see how it scales out.

    Deploy to Windows Azure Staging environment

    Hosted Service When you are sure that there are no bugs just choose Publish in Visual Studio and it will open up a web browser which directs you to the Azure Services Developer Portal, there you can create a new Hosted Service Project or choose an existing one to use for this Proposals service.

    To deploy this solution we have to upload two files; the  App Package containing all your code and references and the Configuration Settings file, both automatically created by Visual Studio.

    Deploying

    When this is done you have to wait a few minutes so Windows Azure can allocate resources for you and prepare the environment. Once this is done you are ready to test your service in the cloud.

    In staging

    Just hit the Run button and after a minute or so the Proposals Service is running - in the cloud!

    Deploy to Production

    For us used to the SharePoint environment and the mess it is to get from development to staging to production environment it’s so much fun to just hit Deploy in Windows Azure to move the Staging service to Production.

    Production

    As you can see from the image above this solution is now in production and started with one worker role.

    Run the workflow

    Now we can test our complete solution by uploading a document containing some comments. Then initiate the Prepare Proposals Workflow.

    Prepare Proposal

    The document will be updated with a new value in the Action column.

    In Progress

    After a few seconds the document is updated by the cloud worker role we created, the workflow completes, there are no more comments in the document and the author should have received an e-mail with information that the workflow is done.

     Done

    Summary

    This was a short demonstration on what you can do with the standard functionalities of Microsoft's cloud offerings such as SharePoint Online and Windows Azure. The scenario was quite simple but using the same techniques you can elevate your SharePoint Online experience and functionality a lot.

    Using Windows Azure is one possibility to host your online custom code, hosting it on on-premise servers is another option and it works just as fine.

    Note: I have not made this sample so it can scale out nor does it handle any exceptions. Take it what its for.

    If you would like to look at the code you can find it here.

    Happy coding!

  • Web Part Properties - part 2 - Editor Parts

    Tags: .NET, C#, SharePoint, Web Parts

    TweetPart This is the second part of the Web Part Properties series. The last post walked through the basics on how to make editable properties on a Web Part. As a sample I used a Web Part that displayed tweets from Twitter - called TweetPart.

    Using the standard approach, by marking the properties using specific attributes, we made the Web Part editable as we wanted. But the user experience, for editing, was not optimal. First of all the properties we wanted to edit was located in their own category at the bottom, not that easy to find for inexperienced/untrained users. Secondly the properties has dependencies and requires validation.

    To WebPart or WebPart

    When developing Web Parts for Windows SharePoint Services 3.0 or Microsoft Office SharePoint Server 2007 you have two different Web Part classes to choose from:

    Which one should I use when building Web Parts? WSS 3.0 supports both…

    Tip: When checking out samples for Web Parts, note which class is used. Most samples on MSDN are using the older construct.

    The first class is a part of ASP.NET 2.0 and the other one is from the Microsoft.SharePoint.dll library. The latter is there to maintain backwards compatibility with SharePoint 2003 (built upon .NET 1.1, which did not have a built-in WebPart class). I strongly recommend using the ASP.NET 2.0 WebPart, since it’s a newer construct and will probably still be used in the upcoming SharePoint 14. The ASP.NET WebPart is still in the new .NET Framework 4.0, according to the PDC 08 pre-release bits, and I doubt that Microsoft will introduce a third WebPart class. What will happen to the SharePoint WebPart class is not known (to me).

    Note: Even though the two classes share the same functionality they differ in how to create custom editing tool panes, how Web Part connections work and how their Web Part Xml definitions look like.

    The EditorPart class

    ASP.NET 2.0 contains an abstract class called EditorPart, this class is used with the ASP.NET 2.0 WebPart class to create customized tool panes. By inheriting from this control you can customize the look and functionality of the tool pane and use standard ASP.NET constructs such as auto post backs, validations etc.

    Tip: since this is standard ASP.NET 2.0 techniques you can have this running outside of SharePoint if you implement your own Web Part based web site.

    In our TweetPart sample we had a drop-down, with the different display modes. Depending on the display mode selection the two text boxes should be shown or not. To achieve this we can create a new EditorPart class and replace the auto-generated Twitter category tool pane. Standard attribute properties, with automatic tool panes, can of course be combined with EditorParts - and in this sample we will leave the count of tweets as a standard attributed property.

    First of all we create a new class which inherits from System.Web.UI.WebControls.WebParts.EditorPart. In this class you have to override two abstract methods and add the controls that you are going to use.

    Add controls

    The controls are added in the CreateChildControls method. This is where you should place most of your control logic, in editor parts, web parts etc.

    Note: Make sure you understand the ASP.NET 2.0 event model!

    I have one select list and two textboxes, representing the different web part properties here.

    protected ListBox m_lbModes;
    protected TextBox m_tbUsername;
    protected TextBox m_tbSearchString;
    
    protected override void CreateChildControls() {
        // Add controls here
        m_lbModes = new ListBox();
        m_tbUsername = new TextBox();
        m_tbSearchString= new TextBox();
        foreach (string mode in Enum.GetNames(typeof(TwitterTimeLineMode))) {
            m_lbModes.Items.Add(mode);
        }
        this.Controls.Add(new LiteralControl("<b>Mode</b><br/>"));
        this.Controls.Add(m_lbModes);
        this.Controls.Add(new LiteralControl("<br/><b>Username</b><br/>"));
        this.Controls.Add(m_tbUsername);
        this.Controls.Add(new LiteralControl("<br/><b>Search string</b><br/>"));
        this.Controls.Add(m_tbSearchString);
    
        base.CreateChildControls();
        this.ChildControlsCreated = true;
    }

    SyncChanges

    The SynChanges method is used by the EditorPart to get the values from the Web Part into the Editor Part.

    public override void SyncChanges() {
        EnsureChildControls();
        TwitterWebPart twitterWebPart = (TwitterWebPart)this.WebPartToEdit;
        if (twitterWebPart != null) {
            // get values from WebPart
            m_lbModes.SelectedValue = twitterWebPart.Mode.ToString();
            m_tbUsername.Text = twitterWebPart.Username;
            m_tbSearchString.Text = twitterWebPart.SearchText;
        }
        return;
    }

    ApplyChanges

    The ApplyChanges method is executed when you click Ok or Apply and is used to set the property values of your Web Part. SyncChanges is always called directly after the ApplyChanges method, to make sure that the properties are in sync.

    public override bool ApplyChanges() {
        EnsureChildControls();
        TwitterWebPart twitterWebPart = (TwitterWebPart)this.WebPartToEdit;
        if (twitterWebPart != null) {
            twitterWebPart.Mode = (TwitterTimeLineMode)Enum.Parse(typeof(TwitterTimeLineMode), m_lbModes.SelectedValue);
            twitterWebPart.SearchText = m_tbSearchString.Text;
            twitterWebPart.Username = m_tbUsername.Text;
        }
        return true;
    }

    Modify the WebPart class

    Now we have to tell the web part that it should use this editor part, instead of the attributed properties. First of all we want to get rid of the automatic interface for the properties, this is done by removing the Personalizable attribute.

    Note: Just removing the Personalizable attribute and none of the others (WebBrowsable etc), will still allow you to configure these properties using tools such as SharePoint Designer.

    Note: Values of properties in the editor part have precedence over automatic generated properties.

    IWebEditable interface

    Now only one thing remains and that is to expose the editor part from the web part. To do this you have to make your web part class inherit from the IWebEditable interface and implement it. Don't forget to add an Id to the EditorPart class.

    EditorPartCollection IWebEditable.CreateEditorParts() {
        // control the editorparts
        List editors = new List();
        TwitterEditorPart editorPart = new TwitterEditorPart();
        editorPart.ID = this.ID + "_editorPart";
        editors.Add(editorPart);
        return new EditorPartCollection(editors);
    
    }
    
    object IWebEditable.WebBrowsableObject {
        get { return this; }
    }

    The CreateEditorParts method is used to tell the web part zone what editor parts you will show, in this case we only have one. But more advanced web parts may require that you have several.

    Tip: You can use the WebPartManager.Personalization status to add different editor parts. For example you can have one for the Shared scope and another for the User scope

    The WebBrowsableObject property is used to get a reference to the Web Part, just return the this object in your editor parts. This property is used by the editor part to get which web part to edit, via the WebPartToEdit method.

    The result

    If we now compile and test this web part we will have an interface that looks something like this. Now we have the edit part located at the top of the tool pane, instead of below - easier to find.

    First...

    It works, but looks awful.

    Make it more user friendly

    We only want the search string to be visible when the Search mode is selected, and the same for the username and User mode, so we have to hook up some events to this editor part. This is standard ASP.NET control programming and easily done.

    To make it look a bit nicer we reuse some SharePoint CSS classes and I also set a title of the editor part…

    protected override void CreateChildControls() {
    
        this.Title = "TweetPart properties";
    
        // Add controls here
        m_editorPanel = new Panel();
        m_editorPanel.CssClass = "ms-ToolPartSpacing";
        this.Controls.Add(m_editorPanel);
    
        m_modesPanel = new Panel();            
        m_modesPanel.Controls.Add(new LiteralControl("<div class='UserSectionHead'>Mode</div>"));
        m_modesPanel.Controls.Add(new LiteralControl("<div class='UserSectionBody'><div class='UserControlGroup'><nobr>"));
        m_lbModes = new ListBox();
        m_lbModes.CssClass = "UserInput";
        m_lbModes.Width = new Unit("176px", CultureInfo.InvariantCulture);
        foreach (string mode in Enum.GetNames(typeof(TwitterTimeLineMode))) {
            m_lbModes.Items.Add(mode);
        }
        m_lbModes.AutoPostBack = true;
        m_lbModes.SelectedIndexChanged += new EventHandler(m_lbModes_SelectedIndexChanged);
        m_modesPanel.Controls.Add(m_lbModes);
        m_modesPanel.Controls.Add(new LiteralControl("</nobr></div></div>"));
        m_editorPanel.Controls.Add(m_modesPanel);
    
        m_searchPanel = new Panel();
        ...
        m_editorPanel.Controls.Add(m_searchPanel);
    
    
        m_usernamePanel = new Panel();
        ...
        m_editorPanel.Controls.Add(m_usernamePanel);
    
        ...
    }

    I use a set of Panel objects, which I hide depending on the selection in the list box. The list box has an event handler for when the selected index changes and reloads the editor part, I also made it automatically post back when the user selects anything in the list box. Check out the source (provided below) for more information.

    Now it looks like this, a whole lot nicer. In upcoming posts I will show you have to make it even one notch better, using templates and less code.

    Final...

    And it works as it should. Also note that we still have the tweet count property as a automatic property, when in shared mode.

    Try it!

    If you would like the code, it’s available here but if you are interested in using the TweetPart you can download the WSP here. Visual Studio 2008 and STSDev are required to compile the code.

    Next part…

    Next part in this series, will focus on how to further improve the experience using Web Part properties and Editor Parts.

    Until next time…

  • Web Part Properties - part 1 - introduction

    Tags: .NET, C#, SharePoint, Web Parts

    I thought that I should kick off this new year with a series of posts on how to make your SharePoint Web Parts editable and how to enhance that out-of-the-box Web Part property editing combined with some tips and tricks.

    This first post may be to most of you SharePoint developers somewhat basic, but I have chosen to start from scratch here. Many of this first post topics are repeatedly asked in the MSDN development forums. The documentation in the SharePoint SDK on this topic is really bad; it just says do this and do that, never why you should do it. Often this makes developers unaware of pitfalls or possibilities.

    Note: Although I talk about SharePoint Web Parts here, most of these techniques can be used in plain ASP.NET 2.0 Web Parts also.

    Sample Web Part - TweetPart

    TweetPart I will throughout this series use a sample Web Part which reads information from Twitter and displays the tweets in the Web Part – called TweetPart. This Web Part will allow the users to choose what tweets to see; the public time line, a user time line or a Twitter search feed. Administrators are allowed to set how many tweets to display.

    All sample code are written using .NET 3.5.

    Properties of a Web Part

    A Web Part class can contain properties which can be edited in the web interface or application development environment. To be editable the property has to be marked with a set of attributes which specifies how and who can edit the property.

    Our sample Web Part needs four properties to work;

    • Display mode – an enumeration on what type of tweets to show
    • User name – a string, if the user time line mode is chosen
    • Search text – a string, if the Twitter search mode is chosen
    • Tweet Count – the number (integer) of tweets to show

    The TweetPart is a Web Part derived from the ASP.NET 2.0 WebPart class, more on this in the coming posts.

    Note: When creating editable properties for your Web Part you have to create properties that are read/write, public and called without parameters.

    I want all of these four properties to appear when someone modifies the Web Part, so I have to mark all four of these properties as WebBrowsable. This indicates to SharePoint that the property can be edited in the web the tool pane. The system will take care of how the user interface will look like; strings will be text boxes, booleans will be check boxes, enumerations will be dropdowns etc.

    Note: A common error here is that the Browsable attribute is used instead, which is used when designing components and controls for visual designers. This attribute was also used when developing Web Parts for SharePoint 2003 with the SharePoint WebPart class.

    To make the properties appear there is one more thing you have to do, you have to add the Personalizable attribute and set the personalization scope. This attribute tells the Web Part Manager that this property value is persisted. If you set the scope to User (default), then users (Members) can modify this property and if it’s set to Shared only editors (Owners) are allowed to change the property.

    Tip: If you omit this attribute, you cannot change it through the web interface, only through code or tools such as SharePoint Designer. This might be a preferred solution in some cases.

    This will make your custom tool pane look like this:

    Custom property

    Now things work, you can edit and save the value of the property and it is stored in SharePoint. But to further enhance the editing experience you should make it more user friendly.

    Make the tool pane more user friendly

    You should give it a name and a description, shown as a tooltip, to show in the editing tool pane that are more user friendly than the name of the property. Don’t rely on that your users or administrators interpret your property names correct. This is done with the WebDisplayName and WebDescription attributes.

    The tool pane has a set of categories (Appearance, Advanced and Layout) which are reserved for the base class properties. The custom properties will end up in a category called Miscellaneous, if you do not provide your own category with the Category attribute.

    Note: You cannot add properties to the reserved categories.

    So this is how we should define our custom properties, at the minimum:

    [WebBrowsable]
    [WebDisplayName("User name")]
    [WebDescription("The Twitter Username")]
    [Category("Twitter")]
    [Personalizable(PersonalizationScope.User)]
    public string Username {
        get;
        set;
    }

    This property now has a friendly name and a description, it’s located under the Twitter category and users can change the value of it, and have their own values.

    Note: If you make changes to it in the Shared view, default if you are an admin, it will be the default values for users who have not personalized the Web Part.

    The same is done for the other three properties and now the Twitter category looks like this when editing the Web Part:

    Shared tool pane view of TweetPart

    Shared only properties and storage

    I want the Tweet count property to be edited only by those who are allowed to edit the Shared view of the web part, therefore I change the PersonalizationScope of the Personalizable attribute to Shared. This means that this property will not be displayed when editing the personal (My) view of the Web Part.

    I also add and specify the WebPartStorage attribute to Shared, this makes the Web Part store only one set of value for this property. Default is the Personal storage mode, which means that every user has it’s own property value.

    Tip: If you set the storage to Shared and personalization scope to User then every user can edit the same (shared) value.

    Now this property looks like this:

    [WebBrowsable]
    [WebDisplayName("Tweet count")]
    [WebDescription("Number of tweets to show")]
    [Category("Twitter")]
    [Personalizable(PersonalizationScope.Shared)]
    [WebPartStorage(Storage.Shared)]
    public int TweetCount {
        get;
        set;
    }

    if you now open up the shared properties of the Web Part, then it looks the same as above, but if you instead go to the personal view then it looks like this:

    Personal tool pane view of TweetPart

    As you can see there is no Tweet Count property to edit, it’s only available in shared mode.

    Tip: To switch between Shared and Personal mode just add this parameter to the query string PageView=[Shared|Personal].

    Run it

    Now we have fixed the configuration of the TweetPart, let’s put it into action. As this series focuses on the editing of the properties I don not go into how I have created the actual rendering of the TweetPart using the Twitter API. It’s pretty simple and you can browse the code to see how it works.

    Public time line User time line Twitter Search
    TweetPart - public time line TweetPart - user time line TweetPart - Twitter Search

    The code

    Download the code sample below. It’s built using STSDev using Visual Studio 2008. If you prefer to just download the finished solution, it’s also available for download.

    Next step…

    Using this method of making your Web Part personalizable is fine, but there are some things that does not make it that user friendly or smooth. First of all the custom categories ends up last amongst the categories – your users might miss the properties to edit. Secondly this sample Web Part, has properties depending on each other (username is only required when using user time line and search text only when using search mode). Your own Web Parts may have more advanced dependencies or require that lists are filled during the editing.

    This is what I’m going to show during the next part of the series.

    Share your experience and stay tuned…

    Technorati tags: , ,

  • PDC 2008: Day 1 and Windows Azure

    Tags: .NET, C#, SharePoint, PDC 08

    Back at the hotel and watching some Monday Night Football (which I could do that in Sweden!). Here is a summary and some reflections on my day.

    Woke up early and walked down to LA Convention Center and got me some breakfast (tomorrow I’ll eat at the hotel). I tried to get to the keynote hall as early as possible for some good seating. I ended up in 6th row and had a good overview of the stage and the huge screens. As this is my first PDC and first conference of this magnitude I’m really impressed with the size and organization of it all.

    Ray Ozzie, Microsoft Chief Architect, hit the stage and did after an introduction introduce Windows Azure – Microsoft’s new cloud server and offering. Windows Azure and the Windows Azure Platform is Microsoft’s way of hosting your services in the cloud. Microsoft will also have a set of services ready; such as Exchange Online, SharePoint Online, Dynamics CRM Online etc. Windows Azure pricing will be based on subscriptions and SLA’s and competitive.

    Windows Azure

    I think the Windows Azure Platform can be really interesting. The thing that really made me interested was that you can federate your Active Directory (and/or your customers) and use that as authentication on your services in the cloud. I really like what Patrik Löwendahl calls it (article in Swedish): “Outsourcing 2.0”.

    After the keynote I went to a session on which I had big expectations: SharePoint Online extending your service. This session was about the SharePoint Online service hosted on Windows Azure. Small summary: SharePoint is hosted by Microsoft and you pay per user! The session and the content was really bad – from several perspectives. First of all we in the audience, several SharePoint MVPs were there, expected more stuff for developers than just SharePoint Designer editing. The only way to add code that makes something real is to host it in a Silverlight application. And then the presenter had a rough mission presenting this non-interesting material for a demanding crowd, especially since this session was an Advanced session! I’ll try to ignore I was there…

    Then I headed over the the Big Room and got stuck when Chris Anderson made a spontaneous demo of the new M-language. It looked really cool when he on-the-fly showed the small crowd how to create a schema from a text and then validate your input and create structured data. Got a book with the draft specification of the language and I will browse it through until tomorrow when Chris and Don Box will have their keynote. After this I tried on some Hands-On Labs with the Windows Azure federated authentication – sweet!

    Chris Anderson demonstrating M

    Then I, and a lot of people, headed over to listen to Anders Hejlsberg (Anders was really the one who made me interested in programming with Turbo Pascal in the 80’s) talk about the future of C#. Anders presented some new stuff that will be in C# 4.0 such as the dynamic keyword, which will combine the features of dynamic languages with C#. Anders made some really nice demos of this, and he actually copied some JavaScript code and pasted it in the C# file, compiled it (just a few small changes) and run it. His demos did receive more applauses than Rays keynote this morning. Some other nice stuff Anders presented was optional and named parameters. He also gave us some hints on what will happen after C# 4.0 – “Eval” in C#! This is what I really look forward to, but that’s long down the road…

    I had hard then deciding which session to attend and I finally selected ASP.NET MVC. Really good session with really good presenters. I like lean and neat HTML code and the MVC model. I hope to get to do some nice projects with this in the future. Unfortunately I’m very bound to SharePoint now so that will likely not happen so soon, if not SharePoint “14” will use this…say no more!?!

    Verne Troyer at PDC 2008

    Last session for today became WF 4.0 – first look which was about the new stuff in Workflow Foundation. Good session and good speakers here too. Tools, persistence and performance was the mantra for this session. WF sounds so cool in English – dub-F, can’t really say that at home in Swedish…

    Then it was freebie time with food and beer in the sponsor area. I now have a set of t-shirts to wear when painting the house. Some interesting sponsors and some interesting give-aways. Did have some time to play with Surface a little more, if I win on lottery I'll order one right away!

    More keynotes tomorrow, more focused on the client side, the bits is distributed and then there is the attendee party at Universal Studios…

  • How to sort XML without XSL in the .NET Framework

    Tags: .NET, C#, XML

    I have several times needed a way to sort XML, retrieved from a file or a web service, inline without invoking XSL transformations, which is the most common way to do it as I have seen.

    The .NET Framework contains the System.Xml.XPath namespace and is available from the .NET Framework 1.1 and up. This namespace contains a number of classes which can improve the performance of your .NET classes when working with XML. Specifically the System.Xml.XPath.XPathExpression contains a method (System.Xml.XPath.XPathExpression.AddSort) to sort the XPath query results.

    The code below shows you an easy way to sort your XML data based on this namespace.

    This is the XML we will use:

    <Entries>
      <Entry id="1">
        <Name>Hello</Name>
      Entry>
      Entry id="2">
        Name>World</Name>
      </Entry>
      <Entry id="3">
        <Name>Test</Name>
      </Entry>
    </Entries>

    To sort this based on the Name element all we have to do is to create an XPathNavigator and add an XPath Expression with sorting like this:

    XmlDocument doc = new XmlDocument();
    doc.Load(@".\data.xml");
    XPathNavigator navigator = doc.CreateNavigator();
    XPathExpression expression = navigator.Compile("Entries/Entry");
    expression.AddSort("Name", XmlSortOrder.Ascending, XmlCaseOrder.UpperFirst,     string.Empty, XmlDataType.Text);
    XPathNodeIterator iterator = navigator.Select(expression);
    foreach (XPathNavigator item in iterator) {
        Console.WriteLine(item.Value);               
    }

    As you can see we create the XPathNavigator from the XmlDocument using the CreateNavigator method (which can be found on XmlNode and derivatives as well) and the create the expression with the sort and executes it using the Select method. Really simple!

    To sort on the id attribute we change the AddSort method call to this:

    expression.AddSort("@id", XmlSortOrder.Ascending, XmlCaseOrder.UpperFirst, string.Empty, XmlDataType.Number);

    Notice the XmlDataType.Number value of the last parameter.

    The sample above will work on the .NET Framework 2.0 and above, since it uses the GetEnumerator() method of the XPathNodeIterator class, which was introduced in 2.0.

    To make it work in .NET 1.1 rewrite the foreach statement with something like this:

    ...
    XPathNodeIterator iterator = navigator.Select(expression);
    while(iterator.MoveNext()) {
        Console.WriteLine(iterator.Current.Value);               
    }

    Hope this one will help you doing crazy workarounds...

    Update:  changed typo in .NET 1.1. code sample...

  • Smooth upgrade of .NET XSL transformations from 1.1 to 2.0 or higher

    Tags: .NET, C#, XML, WinFX

    When .NET 2.0 was introduced, quite a long time ago, the whole System.Xml namespace was re-written, due to the poor performance of the System.Xml implementation. Despite the fact that the CLR 2.0 has been around for a few years there are still implementations using CLR 1.x and especially the XSL transformation bits, since that part is completely re-written and marked as obsolete.

    But note that they are only being marked as obsolete! You can still compile and run most of the code with just a compiler warning. The old .NET 1.1 classes are still in the CLR 2.0, so you can convert your XSL transformations piece by piece and start using .NET 2.0 or even .NET 3.5 since it is based on .CLR 2.0 (read this post by Scott Hanselman to get a better understanding).

    Just make sure that you test everything really thoroughly before putting it in production, since it is not supported.

    I am currently moving one of our large applications to .NET 3.5, which has been working really smooth using .NET 1.1, but now I want to use Visual Studio 2008 and C# 3.0 in the upcoming versions. We will eventually upgrade the XSL transformation parts to use the XslCompiledTransform class, but until then we have to stick with the .NET 1.1 classes.

    I have stumbled upon a few weird things that stopped working after making the upgrade, not all XSL transformations work out fine. The XSLT not() function stopped working in several XSLT files. This is due to that Microsoft has re-written even these old obsolete classes, not just moved them to a new namespace.

    For example I have this XSL snippet, which works fine under a .NET 1.1 compiled environment, which I use to mark alternating lines in different colors.

    xsl:if test="not(position() mod 2)">...

    In .NET 2.0+ I get an System.InvalidCastException when transforming the XSLT, using the old XSLT transformation classes.

    A quick look using the Reflector tool shows us that they have changed the Not function in the BooleanFunctions class (MS.Internal.Xml.XPath.BooleanFunctions in .NET 2.0 and System.Xml.XPath.BooleanFunctions in .NET 1.1). The .NET 1.1 converts the result of the inner expression using the safe Convert.ToBoolean while the .NET 2.0 implementation uses an explicit cast (bool) to convert the result.

    The result of the mod operation is a double according to the MS.Internal.Xml.XPath.NumericExpr.GetValue method in .NET 2.0 and System.Xml.XPath.NumericExpr.getValue in .NET 1.1. Both of them are implicitly casted to objects before casted to booleans.

    // .NET 2.0 not() implementation
    !((bool) query);
    
    // .NET 1.1 not() implementation
    !Convert.ToBoolean(query);

    The same is for all numeric operations (plus, minus, multiplication, division, modulus and negate) inside the not() XSLT function.

    I guess we can't expect a fix for this, even if it would be welcome. But now you know it!

    The problem above was solved with this expression instead:

    xsl:if test="(position() mod 2) = 0">

    P.S. To get rid of the compiler warnings, insert these pragma directives in your C# code:

    #pragma warning disable 0618 // Disable warning CS0618 from here
    // your code goes here
    #pragma warning restore 0618 

  • Using the new ListView control in SharePoint

    Tags: .NET, C#, SharePoint

    The Microsoft .NET Framework 3.5 contains a great new ASP.NET control called ListView. When using the ListView control you have much more control over how the output HTML will look like, which I think still is the main problem with the ASP.NET controls. To learn more about the ListView control, head over to Mustafa Basguns blog and read his excellent articles on the control.

    The ListView control is great when working with SharePoint (WSS3 and/or MOSS 2007) custom pages, since designing SharePoint pages which adapts into the current administration or takes advantage of all the CSS styles demands you to have pretty good control of your HTML.

    To use the ListView control in SharePoint you must first of all download and install the .NET 3.5 Framework on your SharePoint servers. After that you have to edit your web.config manually to get the control to work, otherwise you will get the following error message (if you have enabled error messages, otherwise you will get Unknown Error).

    Unknown server tag 'asp:ListView'. 

    Open web.config in Notepad (or what you prefer to edit it in) and paste the following under configuration/system.web/pages (after the tagMapping element)

    controls>
        add tagPrefix="asp"         namespace="System.Web.UI.WebControls"         assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    controls>

  • Dissecting XPS, part 6 - reading XPS files programatically

    Tags: .NET, C#, XML, XPS

    The sixth part of the Dissecting XPS series is here and this time we will, finally, look at some code for reading XML Paper Specification [1], XPS, files.

    I will in the following sample not use the Microsoft.NET 3.0 Framework, which has built-in functionality for reading and writing XPS files [2]. Instead I will do it using .NET 2.0 (you can try it in .NET 1.1 if you like) and an excellent ZIP library called #ziplib [3]. This will show you more of what's really happening and it will show you how to integrate XPS into applications built using other .NET Frameworks than 3.0 or in Mono or in what ever you like. For instance, you can use Java and the Java Zip packages.

    Getting the parts

    First of all we look how to retrieve the parts from an XPS document. Retrieving a part from an XPS document is as easy as opening the XPS file using the ZIP library and reading out a file. We start with parsing the Start Part relationships from the XPS package.

       1:  using (ZipFile zipFile = new ZipFile(File.OpenRead(fileName))) {
       2:    ZipEntry startPartEntry = zipFile.GetEntry("_rels/.rels");
       3:    XmlDocument startPartXml = new XmlDocument();
       4:    startPartXml.Load(zipFile.GetInputStream(startPartEntry));
       5:  }

    Now the startPartXml object contains the start part relationships for this Open Packaging Convention [4] document, using this file we can find the FixedDocument part, Core Properties part or others using the System.Xml namespace.

    Getting the Core properties

    If we would like to extract the title of the document we just have to parse the Start Part to find the target for the Core Properties Part file and then parse it for the title:

       1:  NameTable nt = new NameTable();
       2:  XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
       3:  nsmgr.AddNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships");
       4:  nsmgr.AddNamespace("cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
       5:  nsmgr.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");
       6:   
       7:  XmlElement coreElm = startPartXml.SelectSingleNode(
       8:    "/rel:Relationships/rel:Relationship[@Type='http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties']",
       9:     nsmgr) as XmlElement;
      10:  string partNamePath = coreElm.GetAttribute("Target");
      11:   
      12:  ZipEntry partNameEntry = zipFile.GetEntry(partNamePath.TrimStart(new char[] { '/' }));
      13:   
      14:  XmlDocument coreXml = new XmlDocument();
      15:  coreXml.Load(zipFile.GetInputStream(partNameEntry));
      16:   
      17:  XmlNode title = coreXml.SelectSingleNode("/cp:coreProperties/dc:title", nsmgr);
      18:  if (title != null) {
      19:      Console.WriteLine("Title of document is " + title.InnerText);
      20:  }
      21:  else {
      22:      Console.WriteLine("Title not found");
      23:  }

    Pretty easy! First of all create an System.Xml.XmlNamespaceManager object which holds the different namespaces that we need to parse the parts (line 1-5). Then select the correct relationship in the Start Part for the Core Properties part (line 7-9). Read the core properties XML (line 10-15)  and finally read the title property (line 17).

    Getting the content

    Getting the rest of the document works in the same way; reading the relationship for the FixedDocument sequence and then retrieve the fixed documents.

    Now you have seen how easy you can start producing your own XPS parsers and readers without using the .NET 3.0 Framwork classes [2] which we will look at next time.

    Further reading and references

    [1] XPS Specification[2] XPS in .NET 3.0[3] #ziplib[4] Open Packaging Convention

  • A Cheat sheet of Cheat sheets

    Tags: .NET, C#, SharePoint, Visual Studio, Microsoft Office, Scripting, AJAX

    Here is a list of cheat sheets for the Windows and .NET platform that I frequently use and I think are of great interest.

    Visual Studio 2005 Keyboard Shortcut References

    SharePoint and Office stuff

    Web and ASP.NET stuff

    Other stuff

  • Updated: Even better encapsulation of getting a value from XmlNode

    Tags: .NET, C#, XML

    I previously suggested a better method for getting attributes for an System.Xml.XmlNode in a response to an post by Marcus. Craig Nicholson highlighted in a comment that the code i provided can be even further optimized.

    private static string GetAttribute(XmlNode node, string name) {     XmlElement elm = node as XmlElement;     return (elm == null) ? string.Empty : elm.GetAttribute(name); } 

    Craig's first improvement includes using string.Empty instead of "". When using "" a new empty string will be allocated in the memory, but the string.Empty will return a reference to an empty string. This will affect garbace collecting performance, since it will have less objects to clean up if you use string.Empty.

    The second improvement Craig supplied was to use the C# conditional ?: operator, to have it on a single line. This will not affect performance since it will be expanded to an if-else statement by the compiler, but the code looks cleaner.

    This is what I really like; clean looking and optimized code!

AWS Tracker

About Wictor...

Wictor Wilén is a Director and SharePoint Architect working at Connecta AB. Wictor has achieved the Microsoft Certified Architect (MCA) - SharePoint 2010, Microsoft Certified Solutions Master (MCSM) - SharePoint  and Microsoft Certified Master (MCM) - SharePoint 2010 certifications. He has also been awarded Microsoft Most Valuable Professional (MVP) for four consecutive years.

And a word from our sponsors...

SharePoint 2010 Web Parts in Action