So I've been investigating .NET mocking frameworks to use for unit testing on one of my current projects... A couple of my needs in particular present a special challenge, and I'm looking for any input from experienced mockers out there on what libraries or tools might be available to address my needs.

Specifically, I am working with a third-party API that doesn't use interfaces. In a lot of cases I am deriving from their classes to add additional functionality, but then calling base-class methods in my new implementation. I need to be able to mock the base class for unit testing. The other big thing is that a lot of their API is static methods, so I can't pass a mock object into my implementation. I need something to intercept the static method call and send it to a mock object instead.

I've been reading about Moq, Rhino Mocks, and Typemock. Typemock seems most likely to handle everything I need, but it's rather expensive and I can't seem to find a trial version or anything that will let me prove it will do what I need. So I'm asking the Internet for suggestions! Anyone?

with 3 comment(s)
Filed under: , ,

So I keep hearing about this EviBlog module for Sitecore and how it blows away the old blogs module and how I just have to check it out. So, I finally found some time over the weekend to do a fresh Sitecore 6.2 install, downloaded and installed EviBlog (you can get it here http://trac.sitecore.net/EviBlog/ by the way), and spent a few minutes playing with it.

Here's the site I created (dunno how long this will be up - if you're really interested in EviBlog, feel free to contact me):

http://www.kevinwilliams.name:8001/TestBlog.aspx

As you can see, I haven't done much with it yet, but I can say that Inline page editing works as advertised and the basic structure seems to be there to handle most blog needs. If the Live Writer integration and RSS feeds work as well, I can see myself using this on future projects for sure.

I linked these in the test blog post above, but if you are interested in EviBlog - I definitely think they're worth watching, so I'll link them again here:

http://www.youtube.com/watch?v=qe3Ppqkxhxw
http://www.youtube.com/watch?v=XQUaXWTJyLs

with 7 comment(s)
Filed under: , ,
Today was like the third time I had to scour Google, SDN, and the Sitecore forums looking for a solution to this problem. So I'm going to post the solution here and hopefully next time I will search my own blog first... Let's say you need to do a Sitecore query such as this:

/sitecore/content/Home/News Section/*

Note the space in "News Section". This causes an error, but there is a solution! Surround the bit that has spaces with pound symbols. Like this:

/sitecore/content/Home/#News Section#/*

This poses the question - how do you escape the # symbol itself if you need to use it? I haven't been able to find that answer, but if you see it - let me know!
with 1 comment(s)
Filed under:

I've just started working with the new Sitecore 6 Page Editor. Yesterday, I noticed something that really bothered me - a content editor user (one who I had placed in the Sitecore Client Authoring role) seemed to have access to the full "Insert From Template" functionality. As I had been very careful to only assign templates where it made sense for certain templates to exist, I was a bit upset that this loophole was available to my content editor. See screenshot below.

In previous versions of Sitecore, I believe the "Insert From Template" functionality was limited to Admin users? Anyway, I needed to remove this option so my content editor wouldn't accidentally add a nonsensical content item in the wrong place. A few searches of the SDN forums later, I found this post with a great response from Ivan Sharamok. The first suggestion was to change the roles the user is in. In this case, I really need this user to be in the Sitecore Client Authoring role. That leaves me with the second option - editing the security for that particular link in the ribbon.

Here's a screenshot of where that is done:

Note, this is done in the Core database, not in Master.

I'm still learning a lot about Sitecore 6, and I'm particularly curious why the checkboxes appear strangely stacked in the security editor for that item. But regardless, this did what I needed - it removed the Insert From Template option from the Page Editor for this user. He is now properly limited to adding only those templates which I have allowed.

Filed under: ,

Alright, it's out.  I've downloaded it, but not installed yet.  I've only just begun reading about the changes and whoah! - way more than I expected!

No more masters?  Three kinds of templates?  Field types renamed?  My head is spinning.  I can't wait to play with this stuff and I'll be sure to share my experiences here on the blog.

Filed under: ,

We have a piece of content on this site we're working on that comes from an outside system instead of Sitecore.  The client has requested that when they are previewing the site, this particular piece of content also be shown as a preview.  Luckily, the outside system allows us to request the content by date.  But I was unsure of how to find out if the site was in preview mode or if it was, what date was being previewed.

Unsure no more!  Jens on the SDN foum came through with this extremely simple solution...  Sitecore.Configuration.State.Previewing (boolean) and Sitecore.Configuration.State.PreviewDate (DateTime).  They do exactly what you'd expect.

No idea how I would have ever found those if it weren't for the SDN forum, though.  Thanks, Jens!

Filed under:

Now, I want to do something a bit more dynamic.  How about we call a web service, get some dynamic data back, and render something based on that data?  In this post, I will build a simple example in order to clearly illustrate the concepts.  But at the end, I will post an example of something a bit more useful to show what can be done!

First off, let's define a simple web service.  I used VS2008's New Item wizard and selected "Web Service" from the dialog.  Then, I replaced HelloWorld() with my own GetData() method.  Here's what the code behind for MyService.asmx looks like:

[WebService(Namespace = "http://tempuri.org/")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

[ToolboxItem(false)]

// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.

[System.Web.Script.Services.ScriptService]

public class MyService : System.Web.Services.WebService

{

    [WebMethod]

    [ScriptMethod]

    public string[] GetData()

    {

        string[] data = new[] { "first data", "second data", "third data" };

        return data;

    }

}

Note I also have uncommented the ScriptService attribute on my class and added a ScriptMethod attribute to my method.  Calling web services from Javascript is a whole lot easier using ASP.NET AJAX.  You'll need to have the ASP.NET AJAX 1.0 Extensions installed for this to work, but it's worth it.  Oh, I'm also using the new array initialization syntax from C# 3.0 in case you've never seen it before.  A real world application would probably query a database or something.

In order to call the web service from Javascript, ASP.NET AJAX requires us to place a ScriptManager on the page with a ServiceReference pointing to the .asmx.  Here's what mine looks like:

<asp:ScriptManager ID="ScriptManager1" runat="server">

    <Services>

        <asp:ServiceReference Path="~/MyService.asmx" />

    </Services>

</asp:ScriptManager>

Thankfully, VS2008's web application project template already set up my web.config to use ASP.NET AJAX.  If you are not using VS2008, you may need to follow the directions at http://asp.net/AJAX/Documentation/Live/ConfiguringASPNETAJAX.aspx to ensure your web.config is set up properly.

At this point, I can call my web service from Javascript and react to whatever data comes back.  The question is - what should it do?  For this post, I think I'll just put up a Silverlight TextBlock and rotate through the web service data when the user clicks on the text.  Here's the XAML:

<Canvas xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

 

    <TextBlock x:Name="MyTextBlock" FontSize="10" FontFamily="Arial" Canvas.Top="10" Canvas.Left="10" Loaded="MyTextBlockLoaded" MouseLeftButtonDown="MyTextBlockClick" />

 

</Canvas>

First, I will retrieve the data from the web service once the text block has loaded by using the Loaded event.  Let me show you the Javascript and then I will explain it...

var index;

var data;

 

function MyTextBlockLoaded( sender, args )

{

    MyService.GetData( GetDataSuccess, GetDataFailed );

}

 

function GetDataSuccess( result )

{

    data = result;

    index = 0;

    UpdateTextBlock();

}

 

function GetDataFailed()

{

    alert( 'Call to MyService.GetData() failed!' );

}

 

function UpdateTextBlock()

{

    var textblock = document.getElementById( '<%= Silverlight1.ControlId %>' ).content.findName( 'MyTextBlock' );

    textblock.Text = data[index];

}

First I declare a variable to hold the current index into the data array and a variable to hold the data itself.  The implementation of the MyTextBlockLoaded() event handler is calling the web service using the proxy built by ASP.NET AJAX.  Note that because this is an asynchronous call, you have to pass in event handlers for both success and failure - that is where my GetDataSuccess() and GetDataFailed() functions come from.  On success, I store the data, set the initial index to 0, and call the function to set the text in the TextBlock.  Note I'm using document.getElementById() to find the Silverlight viewer.  I'm using some inline server-side script to get the Id of the Silverlight viewer from my control (covered in a previous post) to pass to getElementById().  The viewer object has a content property upon which I can call findName() (also covered in a previous blog post) to get a reference to the TextBlock.

The last thing to do is handle the MouseLeftButtonDown event on the TextBlock so that the text changes when the user clicks on it.  Here's that Javascript function:

function MyTextBlockClick( sender, args )

{

    if ( index >= data.length-1 )

    {

        index = 0;

    }

    else

    {

        index = index + 1;

    }

 

    UpdateTextBlock();

}

Here, I increment the index and when the index reaches the end of the list, I reset it to 0 to go back to the beginning.  Then I call UpdateTextBlock() to display the new text.

You can see this example in action at http://www.killeverything.com/zak/Silverlight1/WebService1.aspx.

At the beginning of this post, I promised to show a more useful example.  How about a Silverlight app that displays headlines from an RSS feed and lets you click through to the articles?  If you've been reading my Silverlight posts, there shouldn't be anything too new going on here.  I have just combined several of the concepts I've been learning and blogging about into a single Silverlight app.  You can see it running here: http://www.killeverything.com/zak/Silverlight1/WebService2.aspx and the code for both the simple example and the RSS headline viewer are attached to this post.  If you're a .NET head, you might want to look at the source for the web service where I used LINQ to XML to make parsing the RSS feed easy as cake.  Oh, and I want to point out the clipping I had to add to the TextBlock.  Support for MaxHeight and MaxWidth may be coming in Silverlight 2.0, but clipping is how it's done for now...

Putting a Silverlight viewer on a web page is a lot of work.  You have to import the Silverlight.js file (and make sure it's deployed to the web server), create a div to contain the viewer, and write some Javascript code to call Silverlight.createObject().  To me, this is just begging for an ASP.NET control - so I whipped up one of my own.

So what do I want my control to do for me?  Let's start at the top with the Silverlight.js file.  I want this to be an embedded resource so that I don't always have to remember to copy it in to a new project.  If you're not familiar with this technique, it's been around since .NET 2.0 - keep up! :)  You just throw the Silverlight.js file into your project and set it's build action to "Embedded Resource".  Here's a screenshot:

image

Add it to your project's AssemblyInfo.cs like this:

// Embeded Resources

[assembly: System.Web.UI.WebResource("knw.Silverlight.Silverlight.js", "application/x-javascript")]

Then my control's code tells the page where to find it like this:

Page.ClientScript.RegisterClientScriptInclude("Silverlight.js", Page.ClientScript.GetWebResourceUrl(this.GetType(), "knw.Silverlight.Silverlight.js"));

Here is a link to an article on Code Project that explains the technique in a bit more detail.

Next, I want my control to render the container div for the Silverlight viewer.  This is pretty straightforward - I just override Render() and use the HtmlTextWriter that's passed in.  Here's what it looks like:

protected override void Render(HtmlTextWriter writer)

{

    base.Render(writer);

 

    writer.AddAttribute("id", ID + "Div");

    writer.RenderBeginTag(HtmlTextWriterTag.Div);

    writer.RenderEndTag();

}

Note I'm just concatenating "Div" onto the existing ID of my control when building the div's id, but that should make it unique.

The only thing that's left is the call to Silverlight.createObject().  There are a few variables in this call that I thought could be exposed as properties of my control.  Specifically, the path to the Xaml document, the height and width of the viewer, and the background color.  I'm using C# 3.0, so I took advantage of another language feature - automatic properties.  Here's what that code looks like:

public string Xaml { get; set; }

public int Height { get; set; }

public int Width { get; set; }

public Color BackgroundColor { get; set; }

Lastly, I need to build the actual javascript to create the Silverlight viewer and register it with the page to run as a startup script.  Like this:

string createObjectScript = string.Format("<script>Silverlight.createObject( \"{0}\", document.getElementById( \"{1}Div\" ), \"{2}Ctrl\", {{ width:'{3}', height:'{4}', inplaceInstallPrompt:false,background:'{5}', isWindowless:'false', framerate:'24', version:'1.0' }},{{ onError:null,onLoad:null }},null );</script>", Xaml, ID, ID, Width, Height, ColorTranslator.ToHtml(BackgroundColor) );

 

Page.ClientScript.RegisterStartupScript( this.GetType(), ID + "Create", createObjectScript );

At first glance, that code looks pretty confusing.  All it's actually doing is using string.Format() to build the call to Silverlight.createObject().  {0} is the path to the Xaml, {1} is the ID of the control + "Div" (the id of container div), {2} is the ID of the control + "Ctrl" (a unique id for the viewer itself), {3} is the width, {4} is the height, and {5} is the background color (converted from a System.Drawing.Color using the System.Drawing.ColorTranslator class).  Oh yeah, and you have to escape curly braces when using string.Format() by doubling them.

Ok, that was a lot of work - what has it bought me?  Well, now when I want to use Silverlight on an .aspx page, all I have to do is add a reference to my DLL, register it at the top of the .aspx page, and put the control on the .aspx page somewhere.  Which looks like this:

<knw:Silverlight id="Silverlight1" runat="server" Xaml="MySilverlight.xaml" BackgroundColor="Gray" Height="200" Width="200" />

I will attach the code for both the control and an example of using it to this post.  I'll be using this control in future Silverlight posts here - plus, I do intend to extend it to do more in the future (as I learn more about Silverlight).  So, I'll try to post updates here from time to time.  I hope it's useful to someone! :)

Filed under: ,

Seems I've fallen way behind on my Silverlight blogging as of late.  A few weeks ago, I managed to get some simple animation working.  So, I guess I should blog about it.

Animation is done by transforming your object.  Each graphic element has a RenderTransform property to which you can assign a Transform object to modify your element in some way.  The different types of Transform objects include RotateTransform, SkewTransform, ScaleTransform, and TranslateTransform.  Let's look at an example.

<Ellipse MouseLeftButtonDown="EllipseClick" Height="50" Width="100" Canvas.Top="50" Canvas.Left="50" Fill="Black">

    <Ellipse.RenderTransform>

        <RotateTransform x:Name="EllipseXForm" Angle="90" />

    </Ellipse.RenderTransform>

</Ellipse>

This example is pretty boring - it just renders a 50 pixel high and 100 pixel wide ellipse, rotated 90 degrees (so that it instead appears 100 pixels high and 50 pixels wide).  However, it illustrates the effect that a RotateTransform will have on an object.  Also note that I have named the transform (the x:Name attribute).  The purpose of that will soon become apparent.

Animations are defined within objects called Storyboards.  Basically, a Storyboard defines a timeline of changes that should occur to properties of objects.  For my example, I want to change the Angle property of the RotateTransform object over time (so that the Ellipse rotates slowly as we watch).  Here is the Storyboard I have defined:

<Canvas.Resources>

    <Storyboard x:Name="EllipseStoryboard">

        <DoubleAnimation Storyboard.TargetName="EllipseXForm" Storyboard.TargetProperty="Angle" To="0" Duration="00:00:05" />

    </Storyboard>

</Canvas.Resources>

For this example, I have used a DoubleAnimation.  This is because the property I want to change ("Angle") is of type double.  There are many other animation objects available such as DecimalAnimation, Int32Animation, and ColorAnimation.  The Storyboard.Targetname attribute tells the animation which object it is changing (here's where I use the name I gave my transform earlier) and Storyboard.TargetProperty indicates what property will be changed.  The To attribute is the value the animation should end with and the Duration should be self-explanatory.  Note again, I have named my Storyboard so that I can reference it later.  Oh yeah, and the Storyboard is a resource, so it's defined inside the <Canvas.Resources /> element.

I'm going to need something to trigger the animation to begin.  I've chosen to do it using a mouse click on the ellipse.  So, I will need to add a MouseLeftButtonDown handler to the Ellipse.  Now it looks like this:

<Ellipse MouseLeftButtonDown="EllipseClick" Height="50" Width="100" Canvas.Top="50" Canvas.Left="50" Fill="Black">...

And I need an EllipseClick() function defined in Javascript, so here's what I came up with:

<script type="text/javascript">

    function EllipseClick( sender, args )

    {

        sender.findName("EllipseStoryboard").Begin();

    }

</script>

I placed this directly in my .aspx file for this example.  I don't think I've blogged about findName() before, but Silverlight elements define this method and it allows you to get a reference to any other Silverlight element by name.  Here, I am using it to get the "EllipseStoryboard" Storyboard and executing it's Begin() method.

You can see this example in action at http://www.killeverything.com/zak/Silverlight1/EllipseRotate1.aspx

It's not quite what I wanted, though.  The rotation is happening around the top left corner of the ellipse instead of the center.  Luckily, this was easy to fix - the RotateTransform has CenterX and CenterY properties that allow you to define the point around which the object rotates.  Knowing that the ellipse is 100 wide and 50 tall, this is what I changed the transform to look like:

<RotateTransform x:Name="EllipseXForm" Angle="90" CenterX="50" CenterY="25" />

You can see the finished example at http://www.killeverything.com/zak/Silverlight1/EllipseRotate2.aspx

I've also attached a ZIP with the files needed for these examples in case you want to play with them yourself.

Filed under: ,

It seems several people still haven't heard about Crestone, so thought I'd make a quick mention of it here...  The new Sitecore release (due out mid-year, hopefully) is code-named Crestone.  The beta program is just spinning up, but a few details have leaked out already.  64-bit support is one of the big features.  Also, in-line editing in web preview mode (I've seen this in other CMS's before and it's a huge selling point with customers), a new page layout tool, and a whole new security engine.

Yes, I'm going to apply for the beta program.  If I'm accepted, I won't be able to blog about it for awhile though, unfortunately.  As soon as I have more information to share though, I will!

with no comments
Filed under: ,

For a project I'm currently working on, the client wanted to have a multilist field on one of their templates but have the list of items displayed on the "All" side filtered according to some complex rules.  Normally, you can filter that list by assigning an XPath query to the Source property of the field.  In this case though, the filtering rules were going to be very difficult to implement with XPath and I felt some .NET code was in order.

The solution I chose was to build a custom field type, derive it from the existing MultiList field type, and place my filtering therein.  Turns out all I had to do was override the GetItems method on Sitecore.Shell.Applications.ContentEditor.MultilistEx, call the base implementation to get the initial list of items, then iterate through them - discarding the ones I don't want before returning the list.

Here is a full example using the workflow state code I posted a couple of weeks ago:

public class FilteredMultiList : Sitecore.Shell.Applications.ContentEditor.MultilistEx

{

    protected override Item[] GetItems(Item current)

    {

        List<Item> filteredItems = new List<Item>();

 

        // Call the base class to get the original list.

        Item[] items = base.GetItems(current);

 

        // Loop through the items and filter them.

        foreach (Item item in items)

        {

            // Get the master database.

            Database masterDatabase = Factory.GetDatabase("master");

 

            // We want to exclude items that are not in the final workflow state...

            IWorkflow workflow = masterDatabase.WorkflowProvider.GetWorkflow(item);

            WorkflowState state = workflow.GetState(item);

            if (state == null) continue;

            if (!state.FinalState) continue;

 

            // If we make it this far, add the item to the filtered list.

            filteredItems.Add(item);

        }

 

        // Return the filtered list.

        return filteredItems.ToArray();

    }

If you've never done a custom field type before, installation requires two steps...  First, edit web.config and search for the <controlSources> section.  Add an entry for the assembly and namespace containing your field types.  For example:

<source mode="on" namespace="Your.Namespace" assembly="Your.Assembly" prefix="Prefix" />

What this does is associates the prefix "Prefix" (you can use any name you want) with all field types in Your.Namespace inside Your.Assembly.dll.  You'll see in a second how this prefix is used.

Now, in content editor - expand the System node, right-click on Field Types, select New -> Add From Template.  Expand the System folder, Templates folder, and select the "Template field type" template.  Name the field type whatever you want it to show up when editing a template in template manager.

Fill in the Control field using Prefix:Class syntax where Prefix is the prefix used in web.config and Class is the name of your class that implements this field type.

Now you can go edit a template and add a field using your new field type.  Set the source as usual, but when the user edits an item based on your template, the new field will filter the source list using whatever code you placed in the overridden GetItems!

Filed under:

Today's goal is to display an image and react to a mouse click in some way.  I actually started by reading the QuickStart that gets installed along with the Silverlight SDK.  You can also find it at http://silverlight.net/quickstarts/silverlight10/default.aspx if you still don't have the SDK installed (and why don't you?  Huh?)

It looks like all I need to display an image is an object set to fill with an ImageBrush.  Something like this should work:

<Ellipse Height="100" Width="200" Canvas.Top="10" Canvas.Left="10">

    <Ellipse.Fill>

        <ImageBrush ImageSource="lolcat_quadcore.jpg" />

    </Ellipse.Fill>

</Ellipse>

Bingo, that did the trick.  It looks like this:

lolcat ellipse

Oh wait, I just found the Image object - no brush needed if you do it like this:

<Image Source="lolcat_quadcore.jpg" Canvas.Top="120" Canvas.Left="10" Height="100" />

Which looks like this:

lolcat image

Note that in the first case, the image was automatically stretched to fit the dimensions of the ellipse and in the second, I only specified a height - so the image was automatically scaled proportionally.  Cool!

Now, processing mouse clicks.  This appears to be amazingly easy as well.  First, you need to declare the event handler in the XAML mark-up like this:

<Image Source="lolcat_quadcore.jpg" Canvas.Top="120" Canvas.Left="10" Height="100" MouseLeftButtonDown="ChangeLolcat" />

Then you just need a javascript function to handle the event - mine looks like this:

function ChangeLolcat( sender, args )

{

    if ( sender.Source == "lolcat_quadcore.jpg" )

        sender.Source = "lolcat_schroedinger.jpg";

    else

        sender.Source = "lolcat_quadcore.jpg";

}

In this case, because the MouseLeftButtonDown event is on the Image object, that's the object that gets passed in to the javascript function as "sender".  I am simply changing the Source property from how it was defined in the XAML in response to the mouse click.  And it works! (sorry I can't show you - I don't have a good place to host .NET code at the moment)  I think I'm going to like working with Silverlight.

In case you want to download the code for this project and try it out yourself, I will ZIP it up and attach it to this blog post.

with no comments
Filed under: , ,

Ok, I fell for the hype and decided to try out Live Writer.  If this works like I expect, I will be pretty impressed.  Let me try some stuff...

table1,1 table2,1 table3,1 table4,1
table1,2 table2,2 table3,2 table4,2

Pictures...

 lolcat_schroedinger lolcat_quadcore lolcat_leeeeeroy

 lolcat_dslolcat_spam lolcat_monorail

Alright, this is definitely easier than authoring inside Community Server itself.  I'm sold.  Oh, and thanks Google Images for the lolcats. :)

Filed under: ,

So I finally set out to do something with Silverlight... I set a simple goal for myself tonight - I just wanted to see "Hello World".  That should be easy, right?

First, I downloaded the Silverlight 1.0 SDK from http://www.microsoft.com/silverlight and installed it.

Second, I created a new web site in Visual Studio.

Third, I grabbed a copy of Silverlight.js and added it to the web site.  For me, it was in C:\Program Files\Microsoft Silverlight 1.0 SDK\Tools\Silverlight.js.

I added a link to Silverlight.js in the HTML head of default.aspx.  Like this:

<script type="text/javascript" src="Silverlight.js">

</script>

Next, I added a div in the HTML body of default.aspx and gave it an id.  It doesn't need the runat=server attribute, just an id (it will only be reference from Javascript).  Like this:

<div id="MySilverlightDiv">
</div>

Next, I created a XAML file.  I know next to nothing about XAML yet, so I just used Google to "borrow" someone else's example code for now.  My XAML file is called MySilverlight.xaml and looks like this:

<Canvas xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <TextBlock FontSize="40" FontFamily="Arial" Canvas.Top="20" Canvas.Left="20">

        Hello World!

    </TextBlock>

</Canvas>

Last thing I did was add the javascript to my HTML file to actually create the Silverlight object in my div:

<script type="text/javascript">

    Silverlight.createObject(

        "MySilverlight.xaml",

        document.getElementById( "MySilverlightDiv"),

        "MySilverlightControl",

        { width:'400',

          height:'200',

          inplaceInstallPrompt:false,

          background:'#DDDDDD',

          isWindowless:'false',

          framerate:'24',

          version:'1.0' },

        { onError:null,

          onLoad:null },

        null );

</script>

That's the filename of my XAML file, the Id of my div, a unique Id for the Silverlight control itself, and some various parameters for Silverlight that I do not yet fully understand.

That's it.  I hit my web site with a browser and there was my awesome Hello World!

Hopefully tomorrow I will have time to research XAML some more and do something a bit more interesting with Silverlight.  I hope to extend this simple starter project and continue writing about it here, so if you're interested - copy/paste the code above and come back tomorrow! :)

with 1 comment(s)
Filed under: ,

Something I was working on today required me to figure out a way to determine the current workflow state for a Sitecore item.  Note, this code is running within the context of the content editor (a custom field type, to be exact).  Obviously, an item in the web database had better be in the "Published" state of the workflow. :)

As usual, digging around on the SDN5 site didn't help me out much, but eventually I figured this out:

Database masterDatabase = Factory.GetDatabase("master");
Item currentItem = masterDatabase.Items["/sitecore/content/Home"];
IWorkflow workflow = masterDatabase.WorkflowProvider.GetWorkflow(currentItem);
WorkflowState state = workflow.GetState(currentItem);

In this code, I'm getting a reference to the master database (since I'm working with an unpublished item), getting a reference to my site's homepage (just an example - in my real world code I already have an item reference), and then using GetWorkflow() and GetState() methods I found whlie exploring the Sitecore APIs.

In any case, this seems to work for me.  In my case, I need to know if the item is in the last state in the workflow, so I am checking if state.FinalState is true.

 

More Posts « Previous page - Next page »