David Williams

Who's sruffy looking?

  Home  |   Contact  |   Syndication    |   Login
  19 Posts | 0 Stories | 16 Comments | 0 Trackbacks

News



Twitter












Archives

Post Categories

Microsoft Development

Thursday, September 04, 2008 #

The other night at our local development group, the Charlotte based Enterprise Developers Guild, Brian Hitney from Microsoft gave and Overview of Microsoft ASP.NET MVC.  This is my first time seeing the MVC pattern from Microsoft.  This is the take away Items from this talk which may be helpful to those that are new to the MVC concept. 

Routing

Before discussing the structure of the MVC pattern, it is important to understand how pages are routed through the MVC.  Using a Routing table, links are directed to pages in the following manner:

  • www.Website.com\home\ - goes to homepage
  • www.Website.com\home\data - routes to data page
  • www.Website.com\home\data\14 - routes to data page with index of 14
  • www.Website.com\home\date\edit\14 - I am not certain about this one, but I believe this (or something similar) could be used to route to the data page, edit method with for item 14.  For this to work, the necessary edit method would have to be implemented in the date controller class. 

The basic concept  of the MVC though is the separation of system logic into three separate pieces:

Model

Represented the Data.  In the example the other night, Brian mapped a set of relationships from a database using LINQ/DBML.  In this simple case no other work was done to create the data objects/object models.  As I understand this could also be done using technologies such as NHibernate. 

Controller

This class is where the coding logic for the page goes.  For lack of a better term, this page handles page events (although let me be clear, there are no events in the traditional sense in MVC).  This class would contain methods such as Edit, View, Index etc.  To display individual items, the Data that is generated is sent to the View page.

View

The actual pages that displays the data sent to it from the Control View.  A number of interesting items stood out to me:

  • There is no concept of Page postback in the MVC pattern.  For that reason no page events are handled and processed on the View page. 
  • No ViewState on the page, as the page never posts back to itself.  Because of this the pages are very lightweight.  This also means there is no event processing, and no ability to retrieve Control Data as you would a typical page. 
  • No code behind: The display of items on the Page itself was bound using some classic ASP type syntax.  Rather than using code behind to bind (for example) GridView Items, Items were bound using inline syntax such as <%=Html.TextBox("ProductName")%) or even <%# Eval("ProductName") %>.  This feels like a step backward, but In the end this produces simpler and more lightweight code.  

In the end this model is very different from the traditional ASP.Net model, produces very lightweight HTML, and because of the separation of logic lends itself very well to testing.  On the other hand Brian mention that 90% of Asp.Net web applications in the future are not likely to use this approach. 

Obviously I am only scratching the surface of MVC.  I hope I have accurately described what I have described though.  Of course many more examples can be found as Scott Guthrie's Blog


Recently I needed to create a CustomValidator inside a GridView.  In the end this was relatively straight forward, however I had some problems in my main application.  As I could not find any examples of this on the Internet, I am documenting this here. 

As a proof of concept I created a web page with an UpdatePanel containing a ValidationSummary, a simple GridView and a button.  The GridView was populated by an XMLDataSource (for simplicity), and a column template containing two text boxes and a custom validator.  The Custom validator was validated via code on the server side.  The validation summary correctly displayed all error messages.  I found the following:

  • I did have to set the CustomValidators ValidateEmptyText=True, However ControlToValidate did not have to be set.  This was important as control visibility changed based on the data items.
  • In the CustomValidator_ServerValidate function, I was able to use CustomValidator.NamingContainer to get the Containing GridView Row.  From there I was able to get all of the controls on that row.
  • I did not have to do any binding in the GridView databound event to make this work. For example I did not have to bind the Custom Validator to the ControlToValidate using the Contols ClientID.  I saw talk on some forums about binding the custom validator when building the GridView.
  • The UpdatePanel did not make a difference.

Here is the Code:

 

 

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

<asp:UpdatePanel ID="UpdatePanel1" runat="server">

    <ContentTemplate>

        <div>

            <asp:ValidationSummary ID="ValidationSummary1" runat="server" />

        </div>

        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"

                DataSourceID="XmlDataSource1">

            <Columns>

                <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />

                <asp:TemplateField HeaderText="Validation Test">

                    <ItemTemplate>

                        1:<asp:TextBox ID="TextBox1" runat="server"

                           Visible='<%# Eval("Enter1") %>'></asp:TextBox>

                        &nbsp;2:<asp:TextBox ID="TextBox2" runat="server"

                            Visible='<%# Eval("Enter2") %>' ></asp:TextBox>

                        <asp:CustomValidator ID="CustomValidator1" runat="server"

                            ErrorMessage="CustomValidator" Text="*"

                            onservervalidate="CustomValidator1_ServerValidate"

                            ValidateEmptyText="True"></asp:CustomValidator>

                    </ItemTemplate>

                </asp:TemplateField>

            </Columns>

        </asp:GridView>

        <asp:Button ID="Button1" runat="server" Text="Submit" />

    </ContentTemplate>

</asp:UpdatePanel>

<asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="~/XMLFile1.xml">

</asp:XmlDataSource>

 

Partial Public Class _Default : Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    End Sub

 

    Protected Sub CustomValidator1_ServerValidate(ByVal source As Object, _

             ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs)

        Dim cv As CustomValidator = CType(source, CustomValidator)

        Dim gvr As GridViewRow = cv.NamingContainer

        Dim txt1 As TextBox = gvr.FindControl("TextBox1")

        Dim txt2 As TextBox = gvr.FindControl("TextBox2")

 

        'If String.IsNullOrEmpty(txt1.Text) Or String.IsNullOrEmpty(txt2.Text) Then

        If (txt1.Visible And String.IsNullOrEmpty(txt1.Text)) Or _

                (txt2.Visible And String.IsNullOrEmpty(txt2.Text)) Then

            cv.ErrorMessage = String.Format("Please enter text on row {0}", gvr.RowIndex)

            args.IsValid = False

        End If

    End Sub

End Class

 

<?xml version="1.0" encoding="utf-8" ?>

<customers>

    <customer Id="1" Enter1="true" Enter2="true"/>

    <customer Id="2" Enter1="true" Enter2="false"/>

    <customer Id="3" Enter1="false" Enter2="true"/>

    <customer Id="4" Enter1="false" Enter2="false"/>

</customers>