Archive for the ‘MVC’ category

MiniMVC for WPF

April 24th, 2008

Tonight I presented for the Dayton .Net Developers Group on WPF.  Unlike my previous Lap Around WPF @ CONDG which was meant as a beginners guide to WPF, this time we were skipping the basics and plunging into a framework I’ve dubbed MiniMVC. 

MiniMVC is, primarily, a set of DependencyProperties and custom ICommand’s which allow you to specify a Controller for any FrameworkElement and/or Action in the logical tree.  Unlike Dan Crevier’s D-V-VM pattern or Josh Smith’s MVC pattern implementations which rely on explicitly defining RoutedCommands for each action, binding them up manually, and other unpleasantries (in my humble opinion – these guys still know more than I) with this framework you can use any old class, with any old method, and start executing actions immediately.  Here’s an example:

<Window x:Class=”PostDemo.Window1″
      
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
      
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
      
xmlns:mvc=”http://cromwellhaus.com/wpf/minimvc”
      
xmlns:demo=”clr-namespace:PostDemo”>

    <mvc:MiniMVC.Controller>
        <
demo:Window1Controller/>
    </
mvc:MiniMVC.Controller>
   
    <
StackPanel>
        <
TextBox x:Name=”txtMessage”Text=”" />
        <
Button>
            <
mvc:MiniMVC.Action>
                <
mvc:ControllerAction Trigger=”Click”Action=”Echo”
                      
Return=”{BindingElementName=txtResult,Path=Text}”>
                    <
mvc:ParameterParameterName=”message”
                          
Value=”{BindingElementName=txtMessage,Path=Text}” />
                </
mvc:ControllerAction>
            </
mvc:MiniMVC.Action>
          
Write Something
      
</Button>
        <
TextBlock x:Name=”txtResult” />
    </
StackPanel>
</
Window>

Here’s what’s going on:

First, we have this class, Window1Controller, which we are attaching to the Window’s MiniMVC.Controller property. 

Second, we are setting the MiniMVC.Action property on the Button to a ControllerAction triggered by the button’s Click event.  When Click occurs the Action to be taken on the Controller is Echo.  We want to pass into Echo the value of the txtMessage TextBox Text value as parameter message.  Also, we’re specifying that the Return value from Echo should be applied to the Text property of the txtResult TextBox controller.

Cool?  So what’s really going on?  Well, MiniMVC is handling the most importantly the OnChange event handler for the Action DependencyProperty and using that to dynamically create an ICommand class called ActionCommand.  It’s also looking up the Click RoutedEvent via Reflection and adding the ActionCommand’s Execute method as the event handler for the located Click RoutedEvent.  There is ZERO code in my code-behind.  The Designer has free-reign to apply the Controller and action to any RoutedEvent he/she chooses and we can all sleep well knowing our concerns are separated.  A happy marriage in my book.

I must give a lot of credit to Rob Eisenberg’s super-awesome Caliburn project on which much of the Action dependency property is based.  His framework is full featured to the tilt, but is a little over done to my liking with the extensive use of Dependency Injection.  If you find MiniMVC useful, though, I highly recommend you watch for progress on Caliburn.

You can download the full solution, including demo’s, from the presentation, as well as the above example project here.


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 Checkbox/boolean Value Mapping

December 20th, 2007

In my quest to get my wpfstyle.com site written in the new ASP.Net MVC framework (day 3) I’ve run across a little issue that I’m sure will come up again.

In my world, a checkbox always seemed to imply true/false or yes/no.  In reality, it can mean a lot of things in an Html Form.  It’s an input, remember, and inputs have a value.  When your checkbox is checked, that value is posted back. 

Making it work as a boolean indicator in your MVC application, is possible though.  In keeping with the Membership/Authorization theme from yesterday, I have the following controller action:

public void Authenticate(string userName, string password, bool? rememberMe)
[Hint: Notice the '?' after bool for the third parameter.  That'll be important in a moment.]
Here is the corresponding Login.aspx View which contains a form posting to this action:
<%using (Html.Form("Authenticate", "Account"))
  { %>
    <div style="margin: auto auto 4px auto">Username
        <%=Html.TextBox( "username") %> </div>
    <div style="margin: auto auto 4px auto">Password &nbsp;
        <%=Html.Password( "password") %></div>

    <div style="margin: auto auto 4px auto">
        <%=Html.CheckBox("rememberme", "Remember Me", "true", false)%>
    </div>
    <div><%=Html.SubmitButton( "Log In") %></div>
<%} %>

Looking at our intellisense for Html.Checkbox, we seeimage 

By setting the checkbox’s value to “true” we’re going to have that value sent back through the MVC pipeline to our Action which has a boolean parameter rememberme.  It’s not just any boolean though, it’s a nullable boolean.  Remember when I meantion the distinction that the checkbox being checked causes the value to be posted back?  Well if the checkbox is *not* checked, the rememberme value will be null. 

The MVC pipeline is nice enough to implicitly convert the “true” string to a boolean, but null is not necessarily false in all cases.  To account for this, we must make our parameter a nullable boolean.  Does this maybe cross the line into mixing UI and Controller… eh – possibly?

(NOTE: If you don’t see the Checkbox method in your intellisense, make sure you picked up and referenced the MVC Toolkit)

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!