Archive for the ‘.Net’ category

New Year Indeed

January 15th, 2008

It has been quite a New Year so far.  As of today, Monday January 14th 2008, I have left Speedway and the Speedy Rewards™ team and found new employment with SDS Consulting and I have new eyes courtesy of Lasik Plus of Dayton.  I’d say that’s a fairly ambitious first two weeks.

I’m still working on my side project, hoping to have it completed in the next few weeks or so.  I lost focus with all the holiday excitement, but I’ve picked back up again. 

I’ll also be giving another WPF presentation for the Dayton .Net Developers Group.  This one will be more in-depth than my CONDG presentation which focused on some of the basics of templates, styles, and binding.  One of the big spots in this new version of the presentation will be implementing the MVC pattern within WPF.  Very cool.

ASP.Net MVC and Forms Authentication

December 19th, 2007

So last weekend I picked up the new ASP.Net 3.5 Extensions Preview CTP (and MVC Toolkit) from the ASP.Net team and I’m loving the MVC bits.  I never could get in to MonoRail mainly because I’m a developer diva.  I need intellisense, syntax highlighting, the whole deal.  For a CTP, this release packs quite a punch.

After running through Scott Hanselman’s MVC How-To Screencast and playing around I took to writing a full site I had already 90% completed with Community Server (wpfstyle.com – it’s coming).  Blew threw most of the functionality in the first 3 or 4 hours – awesome.  Then I tried to add Forms Authentication through the easy ASP.Net Configuration button of VS 2008.  Nada.

Long story short, I figured out how to get things working, but there are some manual steps.  Here they are:

image[Step 1] Create a new ASP.Net MVC site.  I’ve called mine SecureMVCApplication.

[Step 2] Lets add a new controller called SecureController.  This will be our set of actions that only administrators can access. 

 

 

image [Step 3] We don’t need to add any new Actions, the Index action created for us is sufficient, but we will need to do something.  So add a call to RenderView(“Index”) within the Index method.  You’ll also need to create the index view, so add a folder called Secure under the Views folder already in your project.  To this we will need to add a new MVC View Page item.  To make it clear, I’ve typed “This is for admin eyes only!!!” as the body of my view.

At this point we should make sure things are working.  Hitting F5 should take you to the root of the site, but you could well end up at /Views/Secure/Index.aspx or something like that.  Try browsing to http://localhost:<port>/secure/index.  You should see the “This is for admin eyes only!!!” text.  If not, go watch Scott’s screencast and come back.

image [Step 4] We’re ready to start securing things.  Use the ASP.Net Configuration button to set security to Internet, create a couple of users and at least 1 role called Administrators.  This is for our example, you can call your roles whatever you want in your application.

At this point, you would normally use the Create Access Rules link to specify the Adminstrators role has access to the secure directory.  Instead, we have to do this bit ourselves, because the MVC pattern will present us with a URL structure that does not map to physical directories.  At least, probably won’t.  In a normal site, the ASP.Net Configuration tool would add a web.config to each configured directory that specifies the authorization rules.  This brings us to the next step:

[Step 5] Open your projects root web.config and add the following:

<location path=”secure”>
  <system.web>
    <authorization>
      <allow roles=”Adminstrators” />
      <deny users=”*” />
    </authorization>
  </system.web>
</location>

Assuming you are familiar with MVC URLs this is telling us that the http://<site>/secure path should allow access to users in the Adminstrators role and deny everyone else.  /secure is, of course, the controller.  Had this been a standard site, the stuff inside the <location /> element would have been found inside our secure\web.config.

[Step 5] We are now ready to authenticate our users, but we don’t have a normal login.aspx.  Instead, we’re going to create a controller called UserController and add a Login and Authenticate action.  Here’s what I’ve added to my sample:

namespace SecureMvcApplication.Controllers
{
    public class UserController : System.Web.Mvc.Controller
    {
        [System.Web.Mvc.ControllerAction]
        public void Login()
        {
            RenderView("Login");
        }

        [System.Web.Mvc.ControllerAction]
        public void Authenticate(string username, string password)
        {
            if (System.Web.Security.Membership.ValidateUser(username, password))
            {
                System.Web.Security.FormsAuthentication.RedirectFromLoginPage(username, false);
            }
        }
    }
}

Notice that my Login action is simply displaying a view.  This view has two textboxes (one marked password) and a submit button.  If you watch(ed) Scott’s Screencast, I’ve used the http://asp.net/downloads/3.5-extensions/MVCToolkit.zip to do this.  The form itself looks like this:

<%using (Html.Form("Authenticate?ReturnUrl=" + this.Request["ReturnUrl"], "User"))
  {%>
    <div>Username: <%=Html.TextBox("username") %></div>
    <div>Password: <%=Html.Password("password") %></div>
    <div><%=Html.SubmitButton("Login") %></div>
<%} %>

Upon Submit/Login, we’re POSTing to the Authenticate( string, string ) Action in our UserController which implements the basic Forms Authentication (above).  The next step is optional, but it helped me watch the authorization status.

[Step 6] (Optional)  Add this to your global.asax.cs to see the authorization status of your requests..

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];

    if (null == authCookie)
    {//There is no authentication cookie.
        Debug.WriteLine("Don't know you, dude.");
    }
    else
        Debug.WriteLine("Enjoy the party!");
}

Now F5 and browse to http://localhost:<port>/secure/index and you should be taken to the http://localhost:<port>/user/login page.  Upon hitting login, you’re directed back to the root of the site.  In our form, we had to manually set the ReturnUrl, because Forms Authentication assumes you will be posting back to yourself (classic ASP.Net Web Form).  We’re posting across to the Authenticate action Url.

You can download the completed VS 2008 project I used here.

Can you believe we’re already calling ASP.Net Web Forms “classic”?  Now we need to get MVC into the WPF platform.  How cool would that be!

NHibernate Query Generator Installer for Visual Studio 2008

December 7th, 2007

imageI posted recently a manual .reg file for adding the NHibernate Query Generator custom tool to Visual Studio 2008.  I just sent Ayende an update to the .Setup Product.wxs, a WiX file, which adds a new fixture specifically for 2008. 

If you are interested in building the installer and running the trunk of NHQG, below is my batch script.  Obviously, you’ll have to change a couple of paths, but it should get you started. 

You can download the Product.wxs pending Ayende approving the new Product.wxs file here.

echo Off
set path=%path%;c:\tools\svn-win32-1.4.4\bin

echo get Trunk (Non-Recursive)…
svn co
https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk trunk -q -N
echo done

echo get Art…
svn co
https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk/Art trunk/Art -q
echo done

echo get SharedLibs…
svn co
https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk/SharedLibs trunk/SharedLibs -q
echo done

echo get NHQG…
svn co
https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk/NHibernate.Query.Generator trunk/NHibernate.Query.Generator -q
echo done

echo build NHQG…
pushd .
cd trunk\NHibernate.Query.Generator
%windir%\Microsoft.NET\Framework64\v2.0.50727\msbuild.exe default.build
echo done

echo build Installer
cd NHibernate.Query.Generator.Setup
%windir%\Microsoft.NET\Framework\v2.0.50727\msbuild.exe Setup.wixproj
echo done
popd
PAUSE

PerformanceHelper.cs Update: Perfmon, Console, and Debug Output options

October 27th, 2007

I’ve updated my PerformanceHelper class that I’ll throw around certain code blocks to help trend or monitor performance.  Before it was merely a PerformanceCounter wrapper with a few metrics, but now you can specify Console, Debug and/or Perfmon.  You do this by using an XOR ( ’|’ ) in a new Constructor.  Here’s an example which outputs to Debug.WriteLine and PerfMon:

for (int index = 0; index < 10; index++)
{
    using (new PerformanceHelper("ConsoleSample",
        "Perfmon Sample", OutputOptions.Debug | OutputOptions.Perfmon))
    {
        Thread.Sleep(500);
    }
}

The method that does the Output to Console and Debug is marked as [Conditional("DEBUG")], because you really should have a better strategy for performance monitoring in production and you don’t want that hit for each block that you wrapped.

Note to Vista Developers:  You will have problems creating custom performance counters at runtime based on registry access.  To support this in a client based app, you will need to specify an application manifest and mark it with the following:  

<requestedExecutionLevel  level="requireAdministrator" />

For more information on application manifests, read this.

WPF Controls TabIndex: Moving to the First Input Control

October 25th, 2007

Here’s one of those real-world situations that no one bothers to demo.  If you are building a form or have some sort of input your gathering from the user, you’ll likely want the first input control Focused initially.  You have a few ways to do this (in ascending order of recommendation):

  1. Call Focus() on the first control explicitly (meh).
  2. Iterate the controls collection and find the lowest TabIndex (terrible code smell).
  3. Do the following in the Load event:
this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));

Lap Around WPF @ CONDG

September 28th, 2007

This evening the Central Ohio .NET Developers Group was nice enough to let me present on WPF.  Everything went fairly well, though it was more a test of my efficiency in WPF development than I had planned; I managed to leave behind the external hard drive that had my code-snippets, slides (both of them), and project template.  So we went from nothing to code-kinda-complete in about an 1 hour and 45 minutes. 

I was very happy with the number of questions and that at least a few people stayed behind to talk afterwards.  If Jim has an opening, I am hoping to give the same presentation again here in Dayton (hint, hint). 

For those that are interested I’ve posted the Demo project, Time Machine, for your general amusement.  If there are any questions or comments regarding the presentation or the demo, feel free to post them and I’ll do my best to answer them.

Thanks to everyone who showed up and for all your questions.

Visual Studio 2008 Beta 2, Team Explorer, and Codeplex

August 8th, 2007

If you happen to use CodePlex as I do, I hope you found Team Explorer for Visual Studio 2005 to be a huge productivity boost.  With Visual Studio 2008 it wasn’t entirely obvious to me how to replicate this setup.  It turns out that Team Explorer can be installed individually from the Visual Studio Team Foundation Server 2008 Beta 2 (what a mouthful) installer without all the extra gunk.  I figured this out when I noticed the Team Explorer for 2005 installer had a graphic for Team Foundation Server. 

So go grab the Microsoft Secure Content Downloader and its a ridiculously quick 1.5gb download – about 45 minutes over my Timewarner cable connection.

Binding to an Image Byte[] in WPF

July 26th, 2007

I’m working on a WPF app for my wife who coaches our local high school track team.  One of the features she wanted was to have some images for different players and teams and, religious debate aside, I have chosen to save these in SQL Server 2005.  I’m using NHibernate for all my data access which has been a great experience (my first).  Impressively, NHibernate supports SQL Server Image columns via the inherent Byte[]  type (See Section 5.1.9 of the docs).  This made adding the Image to my classes very easy. 

Here’s a snippet of my class with the corresponding NHibernate Mapping Xml File:

/* Class */[Serializable]public class Organization : INotifyPropertyChanged{       //...

    public byte[] Image    {        get { return _image; }        set        {            _image = value;            OnPropertyChanged("Image");        }    }

    //...}  
<!-- Mapping --><hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">  <class name="Cromwell.MyApp.Organization, Cromwell.MyApp"          table="dbo.Organization">    <id name="Id" type="Int32" column="Id" unsaved-value="0">      <generator class="native" />    </id>    <many-to-one name="Type"                  class="Cromwell.MyApp.OrganizationType, Cromwell.MyApp"                  column="Type"                  not-null="true"/>    <property name="Name" type="String" length="255" column="Name" not-null="true"/>    <property name="Address1" type="String" length="255" column="Address1" not-null="false"/>    <property name="Address2" type="String" length="255" column="Address2" not-null="false"/>    <property name="City" type="String" length="255" column="City" not-null="false"/>    <property name="State" type="String" length="2" column="State" not-null="false"/>    <property name="PostalCode" type="String" length="7" column="PostalCode" not-null="false"/>    <property name="Image" type="Byte[]" column="Image" not-null="false" />  </class></hibernate-mapping>

The key to binding this Image property on my WPF forms is the Binding Converter property.  This property allows you to specify any class which implements System.Windows.Data.IValueConverter to act as an intermediary between your bind data and WPF.  In my case, the goal was to turn a byte[] property, Image, into a BitmapImage which the an <Image /> control/element can display. 

Here’s what I came up with:

class BinaryImageConverter : IValueConverter{    object IValueConverter.Convert( object value,         Type targetType,         object parameter,         System.Globalization.CultureInfo culture )    {        if(value != null && value is byte[])        {            byte[] bytes = value as byte[];

            MemoryStream stream = new MemoryStream( bytes );

            BitmapImage image = new BitmapImage();            image.BeginInit();            image.StreamSource = stream;            image.EndInit();

            return image;        }

        return null;    }

    object IValueConverter.ConvertBack( object value,         Type targetType,         object parameter,         System.Globalization.CultureInfo culture )    {        throw new Exception( "The method or operation is not implemented." );    }}

Here’s how I used it in my WPF Page:

<Page x:Class="Cromwell.MyApp.EditOrganization"    ...      xmlns:converts="clr-namespace:Cromwell.MyApp.Converters"    >    <Page.Resources>      <converts:BinaryImageConverter x:Key="imgConverter" />    </Page.Resources>    <Grid>    <!-- Image Control -->    <Image Source="{Binding Path=Image,                     Converter={StaticResource imgConverter}}"            Stretch="UniformToFill"       StretchDirection="Both">      <Image.BitmapEffect>        <DropShadowBitmapEffect Color="Black" />      </Image.BitmapEffect>    </Image>  </Grid></Page>

I’m going to have to spend some time in the WPF profiler, but this is a big step.  Pretty cool how simple it was and very clean.

WPF ScaleTransform Direction

June 28th, 2007

The key to scaling your WPF elements in a specific direction other than down and to the right are the CenterX and CenterY properties of the ScaleTransform.  It’s easy enough to set these manually, but that’s just lazy and asking for long term trouble.  Instead, decide how you want it to animate and bind it to something.  For instance, I have a touch screen keyboard I’m working on that I’d like to animate Up and to the Right when you are holding down the key.  Here’s how I did it:

<Page xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  <Button Margin="5,5,5,5" Width="50" Height="50" x:Name="btnKey">
    My Button
    <Button.RenderTransform>
      <ScaleTransform x:Name="buttonscale" ScaleX="1" ScaleY="1" CenterX="0" CenterY="{Binding ElementName=btnKey, Path=ActualHeight}" />
    </Button.RenderTransform>
    <Button.Triggers>
      <EventTrigger RoutedEvent="Button.Click">
        <BeginStoryboard>
          <Storyboard>
            <DoubleAnimation Storyboard.TargetName="buttonscale" Storyboard.TargetProperty="(ScaleTransform.ScaleX)" To="1.5" Duration="0:0:0.25" AutoReverse="True"/>
            <DoubleAnimation Storyboard.TargetName="buttonscale" Storyboard.TargetProperty="(ScaleTransform.ScaleY)" To="1.5" Duration="0:0:0.25" AutoReverse="True"/>
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger>
    </Button.Triggers>
  </Button>
</Page>

The key is that I bound the CenterX proeprty to the button’s ActualHeight property.  If you wanted to scale from some midpoint though, you’ll have to specify a Converter in your bind syntax.  This Converter technique is often cited in the ubiquitous “Reflection trick”.

Bind to Method within a DataTemplate

June 12th, 2007

One of my play projects with WPF is a photo viewer for the pictures we put out on http://cromwellhaus.com.  One of the views is a montage of the latest photos with a random RotateTransform Angle applied to each image’s RenderTransform.  Getting the view itself set up as cake, but when I attempted to apply the random angle to each image, it wasn’t so random.

Here’s what happened and how to actually accomplish such a task:

I started out with an ItemsControl, rather than a ListView as most examples show, using a UniformGrid as the ItemsPanel.

<ItemsControl ItemTemplate="{StaticResource photoItem}" ItemsSource="{Binding Source={StaticResource dpPhotos}, XPath=/rss/channel/item}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <UniformGrid HorizontalAlignment="Stretch"  VerticalAlignment="Stretch" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
</ItemsControl>

I bound the ItemsSource to an XmlDataProvider pointing to the photos RSS feed for Ryan Jr. pictures

<XmlDataProvider x:Key="dpPhotos" Source="http://cromwellhaus.com/photos/baby/pictures_rss.aspx?Tags=Ryan+Jr&amp;AndTags=1" XmlNamespaceManager="{StaticResource rssMapping}"/>

I run our site using Community Server 2007 Express Edition which provides RSS meta extensions for more detailed feeds.  This required that I apply an XmlNamespaceManager to define these extension namespaces.  That’s what this is for:

<XmlNamespaceMappingCollection x:Key="rssMapping">
  <XmlNamespaceMapping Uri="http://search.yahoo.com/mrss" Prefix="media" />
</XmlNamespaceMappingCollection>

Here is the DataTemplate used by the ItemsControl to display/render each image.  You’ll see this referred to in above as {StaticResource photoItem}:

<DataTemplate x:Key="photoItem">
  <Image Margin="12,12,12,12" Source="{Binding Mode=Default, XPath=media:thumbnail/@url}" ToolTip="{Binding XPath=title}" Width="{Binding Mode=Default, XPath=media:thumbnail/@width}" Height="{Binding Mode=Default, XPath=media:thumbnail/@height}" />
</DataTemplate>

You can see the use of the XmlNamespaceMapping in the XPath=media:thumbnail/@url.  That had me stumped for a few seconds, but opening the project up in Expression Blend and re-adding the XmlDataProvider created the Mappings for me.  (Sidebar: VS 2008 does do this for you – thank goodness)

At this point, we are displaying thumbnails and we are certainly aware that I make poor color choices, but we’re on our way.

Almost there...

Applying the RotateTransform is easy…

<Image Margin="12,12,12,12" Source="{Binding Mode=Default, XPath=media:thumbnail/@url}" ToolTip="{Binding XPath=title}" Width="{Binding Mode=Default, XPath=media:thumbnail/@width}" Height="{Binding Mode=Default, XPath=media:thumbnail/@height}">
  <Image.RenderTransform>
    <RotateTransform Angle="10" />
  </Image.RenderTransform>
</Image>

…and it’s almost as easy to use the System.Random class to generate the angle.  Just add the following ObjectDataProvider as a Window or Application Resource and bind the Angle property to it:

<ObjectDataProvider x:Key="randomAngle" ObjectType="{x:Type system:Random}" MethodName="Next">
  <ObjectDataProvider.MethodParameters>
    <system:Int32>-12</system:Int32>
    <system:Int32>12</system:Int32>
  </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

...
<RotateTransform Angle="{Binding Source={StaticResource randomAngle}" />

Well when you do this, you’ll find that you get the same Angle for every image.  This is because you are actually binding to a single instance of the ObjectDataProvider.  To resolve this we actually have to embed the ODP in the transform itself as so:

<RotateTransform>
  <RotateTransform.Angle>
    <Binding>
      <Binding.Source>
        <ObjectDataProvider ObjectType="{x:Type system:Random}" MethodName="Next">
          <ObjectDataProvider.MethodParameters>
            <system:Int32>-12</system:Int32>
            <system:Int32>12</system:Int32>
          </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
      </Binding.Source>
    </Binding>
  </RotateTransform.Angle>
</RotateTransform>

Tada!image

Now you will find that your angle’s aren’t terribly “Random”.  This is because you are actually asking for a new instance of the Random class each time.  You can tell the ODP within the DataTemplate to use the same instance each time by adding this to the Window Resources:

<ObjectDataProvider x:Key="randomAngle" ObjectType="{x:Type system:Random}"/>

and modifying the Angle binding to the following, telling the transform ODP to use a specific resource instance rather than just giving it a type to instantiate each time.

<ObjectDataProvider ObjectInstance="{StaticResource randomAngle}" MethodName="Next">
  <ObjectDataProvider.MethodParameters>
    <system:Int32>-12</system:Int32>
    <system:Int32>12</system:Int32>
  </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

You can download a mini-version used to write this post here.