Tag Archives: ASP.NET

Review: Microsoft .NET – Architecting Applications for the Enterprise, 2nd Edition

I’ve recently finished reading Microsoft .NET – Architecting Applications for the Enterprise, 2nd Edition by Dino Esposito and Andrea Saltarello. This book caught my attention for two reasons. First, I really enjoy software architecture. Second, I’ve read lots of work by Dino and always found them enjoyable.

The book gives examples of a few architectural patterns like Domain Driven Design (DDD), Command Query Responsibility Segregation (CQRS), and Event Sourcing. It starts with a pretty heavy focus on DDD and seems to assume that you’ve read *The* Domain Driven Design book by Eric Evans. I’ve only skimmed through that book, but it was enough to get many of the references. This book does cover the high level definitions of DDD in a way that the reader can jump right in. The accompanying source code even provides the same example in DDD and CQRS (the two main architectures being discussed).

There were two major things I liked about this book. I really enjoyed how the book isn’t presented as ‘this is the best software architecture, so you should use it.’ Things are presented in a way that clearly states the authors’ position on each architecture. For example, DDD is discussed as a the typical go-to architecture for enterprise systems. It’s a proven pattern that ‘just works’ in many cases. The discussion of CQRS clearly identifies some weaknesses in DDD and supplies an alternative with the explicit caveat that a CQRS-based architecture will change how you think about data.

The other main point I liked about the book is how real-world the discussions are. I usually get that feeling from Microsoft Press books. Early on the authors say, “To design a system that solves a problem, you must fully understand the problem and its domain.” In one of my previous positions, one of the first things I asked when joining the team was, “How have you documented what we’re trying to build?” I received a weird non-answer from the team’s senior developer. I went to the team’s manager and asked the same thing so I could understand the requirements gathering and technical design analysis that went into the product. He said, “We don’t have any of that — we’re Agile.” I thought he was joking, but he wasn’t. Obviously it would strike a chord with me when the authors said, “Agile architecture is sometimes presented as an oxymoron, like saying that if you’re agile you don’t do any architecture analysis, you just start coding…” Elsewhere they described the businessman-developer disconnect that occurs when requirements are incomplete, which is exactly what happened on the previous team I mentioned. It’s like I always say, “If you don’t know where you’re going, how will you get there?”

Another aspect of the book that I think can get buried in reading is the point about developing for a task-based user experience. Too often do developers start coding at the database and work their ways up to the user interface. Without a clean architecture, this can lead to situations where a column in your relational database has to change all the way to the UI. That’s silly. With a good architecture that clearly identifies boundaries in code, you inherently create more reusable and more maintainable code. I think this should be everyone’s main goal while writing code.

I also thought it was cool how the book and accompanying example code demonstrate using a NoSQL database (RavenDB) for an event sourcing application. While I don’t know where I’d ever use Event Sourcing over a more common architecture (mainly because I have to account for the expertise of other developers), I really like the Event Sourcing pattern. Now that Akka.NET is gaining traction, I wonder if Event Sourcing will become the way of the future.

One minor issue I had with the companion content was that it didn’t run as-is. There was a problem with the NuGet packages and MVC5 for which I found a solution at https://naa4e.codeplex.com/workitem/1.

I would definitely recommend this book for senior developers and engineers. It provides concrete examples and guidance from experienced architects toward more solid enterprise application design.

You can download the companion code for the book at https://naa4e.codeplex.com/

Flattr this!

Software Abstractions take Skill.

I recently read Adaptive Code via C# and posted a review on Amazon:

This book is a new favorite of mine. I’ve always prided myself on writing clean and concise code. I’ve always been fond of SOLID principles. I wanted to read this book to keep my understanding of SOLID principles fresh. It also covers design patterns, although be aware that it’s not an in-depth design patterns book.

The book is broken into three sections. The first section is an introduction to Scrum and SOLID. Before I had even finished the first section, I was already recommending this book to colleagues. This leading content isn’t necessarily targeted toward developers. I think many managers or team leaders could benefit from reading the basics of Scrum and understanding the terminology for SOLID programming.

I already had a pretty solid (sorry for that) understanding of SOLID principles, so I felt like the second section was more of a refresher. In that vein, I think it’d be hard for me to definitively say how easily digestible this section will be for beginners. I think it will greatly help intermediate or expert engineers to gain a new understanding of software architecture. The book’s audience is meant to be intermediate and expert engineers, but I think beginners could get the content. It’s so well written and clearly explained that I think anyone who might struggle a little with the concepts presented in the book could easily substitute any gaps in understanding with Wikipedia or blogs. Though, I honestly felt like there were no gaps. This section may be boring for non-developers, although I know project managers, program managers, and directors that would find this section interesting. The biggest thing to keep in mind is that SOLID principles are not rules; they’re guidelines.

I thought the last section was excellent. It is split into three chapters in which you’re presented with somewhat realistic dialog (‘fortnight’) that follows a small team through the first two sprints for a chat application. I’ve read a few books on Agile and Scrum methodologies and this section was probably the most fun to read on the topic. It could just be that it’s written as a script with code examples, but it was refreshing and easy to follow.

This book does a great job at explaining technical debt. While reading the book, I realized nobody at my current job has ever said the term ‘technical debt’. I asked around and found that it was a new term to most. The concept of technical debt is one thing I know I had problems understanding as a beginner. As developers become more mature, they begin to understand that the field is usually roughly equal parts business and technology. It’s really important to understand these ‘trade-offs’ and the last section demonstrates pretty well how technical debt occurs.

If you’re on the fence about purchasing this book, you should buy it. It’s a quick read and an understanding of the subject matter will improve your software. I’ve never regretted purchasing a Microsoft Press book.

I gave a short presentation at work recently about SOLID principles, so I was stoked to have a chance to read this book. One of the biggest takeaways I hope anyone has from this book is the ability to abstract software in useful ways.

I recently solved an issue using techniques such as those presented in this book. Specifically, this solution included the Open/Closed Principle, Dependency Injection, and Single Responsibility Principle as well as the Decorator pattern. The issue was simple, one I’m sure many people have encountered in their time with C#; a dataset’s DataRow does not inherent from IDataRecord in the same way something like SqlDataReader does.

Suppose you have a domain model of some kind that you need ‘mapped’ from your database into a single object.

Here’s a demonstration of the problem. I use a csv of cars from Wikipedia and instead of mapping to a domain object, I write out to the console.

First, an example using a DataReader:

using (var connection = new OdbcConnection(connectionString))
{
    connection.Open();
    using (var cmd = connection.CreateCommand())
    {
        cmd.CommandText = "select * from Cars.csv";

        using (var reader = cmd.ExecuteReader())
        while (reader.Read())
        {
            OverloadedDumpRow(reader);
        }
    }
}

Now, an example using a DataRow:

using (var connection = new OdbcConnection(connectionString))
{
    connection.Open();

    var adapter = new OdbcDataAdapter("SELECT * FROM Cars.csv", connection);

    DataSet ds = new DataSet("Temp");
    adapter.Fill(ds);

    foreach (DataRow row in ds.Tables[0].Rows)
    {
        OverloadedDumpRow(row);
    }
}

Aside from the implementation of data retrieval, OverloadedDumpRow should look exactly the same for both examples:

Console.WriteLine("A {0} {1} {2}", 
    row["Year"], row["Make"], row["Model"]);

The problem is that, since these two implementations don’t share a common base type of any sort (DataRow derives from nothing). This isn’t really an issue in a small example like this, but if you have a complex domain and you want to return data from your database and parse that data consistently. Think about what you’d have to do for each and every domain model just to parse resultsets from IDataRecord and DataRow. How do you determine whether or not you’ll even *need* both implementations? To be DRY, you’d need to pull your data from the following methods into variables or directly into your target domain object:

static void OverloadedDumpRow(IDataRecord row)
{
    Console.WriteLine("A {0} {1} {2}",
                    row["Year"], row["Make"], row["Model"]);
}

static void OverloadedDumpRow(DataRow row)
{
    Console.WriteLine("A {0} {1} {2}",
                    row["Year"], row["Make"], row["Model"]);
}

Obviously, this isn’t reusable. What we’d need is an interface. Something like this:

public interface IStringIndexed
{
  object this[string key] { get; }
}

Then, we could implement the redundant methods above in a single method:

static void DumpRow(IStringIndexed record)
{
  Console.WriteLine("A {0} {1} {2}",
    record["Year"], record["Make"], record["Model"]);
}

To get from IDataRecord and DataRow to this target interface, you’ll need an adapter. An adapter decorates a target type and exposes some new interface for that type. This can be a little confusing in our case because IDataRecord and DataRow have the same functionality (returning an object by string index), but they don’t have a consistent interface allowing us to write abstractions on top of these two types.

Our simple interface follows the single responsibility principle (implementations can only get an object by key) as well as the open/closed principle (you can now write extension methods against IStringIndexed).

Writing an adapter to use the interface from above is ridiculously easy. Here’s one of them:

internal class DataRowStringIndexedWrapper : IStringIndexed
{
    private readonly DataRow _row;

    public DataRowStringIndexedWrapper(DataRow row)
    {
        _row = row;
    }

    #region IStringIndexed Members

    object IStringIndexed.this[string key]
    {
        get { return _row[key]; }
    }

    #endregion
}

You would wrap an IDataRecord in exactly the same way.

Here are the two updated examples (notice both of these dump the record to console using the same method):

using (var connection = new OdbcConnection(connectionString))
{
    connection.Open();
    using (var cmd = connection.CreateCommand())
    {
        cmd.CommandText = "select * from Cars.csv";

        using (var reader = cmd.ExecuteReader())
        while (reader.Read())
        {
            DumpRow(new DataRecordStringIndexedWrapper(reader));
        }
    }
}

using (var connection = new OdbcConnection(connectionString))
{
    connection.Open();

    var adapter = new OdbcDataAdapter("SELECT * FROM Cars.csv", connection);

    DataSet ds = new DataSet("Temp");
    adapter.Fill(ds);

    foreach (DataRow row in ds.Tables[0].Rows)
    {
        DumpRow(new DataRowStringIndexedWrapper(row));
    }
}

This is the power of following SOLID principles and studying design patterns. This example isn’t taken from the book, but you’ll learn these skills and more in the book.

Code

A console application of this example is available on github.

You can purchase Adaptive Code via C# from informIT or Amazon.

Flattr this!

ASP.NET, AppDomains, and shadow-copying

I answered a question on StackOverflow nearly two years ago, and I’m surprised at how few votes it has received, despite comments such as:

+1 for teaching me something new today thanks. -kobe

Being one of my favorite answers, I thought I should discuss it on my blog a little more in-depth than just posting the SO answer. I’d like to briefly discuss what ASP.NET really is (in the context of IIS), why AppDomains are needed, and lastly what shadow-copying does for an application. There is no code associated with this post, and it is driven more by contemplation than by a specific resolution to a problem. So, I apologize in advance if it seems disjointed at times.

Continue reading ASP.NET, AppDomains, and shadow-copying

Flattr this!

ASP.NET BuildResultCompiledAssembly error

Unable to cast object of type ‘System.Web.Compilation.BuildResultCompiledAssembly’ to type ‘System.Web.Compilation.BuildResultCompiledGlobalAsaxType’.

This has been reported as a bug.

But there is no solution. The problem, for me at least, is the following in AssemblyInfo.cs:

[assembly: AssemblyCulture("en-US")]

You can’t have a value here in a main assembly. By adding “en-US” to this attribute, I’m telling the .NET framework that this is a satellite assembly. In an ASP.NET application, that’s not good. (see also)

The Fix

Change it back to:

[assembly: AssemblyCulture("")]

Flattr this!

Using DataAnnotation attributes to validate Membership password

As a follow-up to my post on DataAnnotations in ASP.NET Web Forms, I’d like to demonstrate yet another custom attribute. Although ASP.NET offers a CreateUserWizard, if your custom membership provider is way more complicated, you will probably be better off creating a control from scratch. If you go this route, you’ll have to provide some of the functionality from the CreateUserWizard. Here is a simple attribute which checks *only* password complexity and builds an ErrorMessage without ever calling the CreateUser method.

This attribute can be added to a password property and validate against the *Default* Membership Provider.

Here is the code:


    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
    public class MembershipPasswordRequiredAttribute : ValidationAttribute
    {
        public override bool IsValid(object value)
        {
            if (value == null || !(value is string) || string.IsNullOrEmpty(value.ToString()))
            {
                return false;
            }

            MembershipSection membershipConfig = (MembershipSection)WebConfigurationManager
                                                                    .GetSection("system.web/membership");
            var providerSettings = membershipConfig.Providers[membershipConfig.DefaultProvider];
            string minLength = providerSettings.Parameters["minRequiredPasswordLength"];
            string minAlpha = providerSettings.Parameters["minRequiredNonalphanumericCharacters"];

            if (string.IsNullOrEmpty(this.ErrorMessage) && !string.IsNullOrEmpty(minLength))
            {
                string message = String.Empty;
                message = String.Format("Password must be at least {0} characters in length", minLength);
                if (!string.IsNullOrEmpty(minAlpha))
                {
                    message = String.Format("{0} and contain at least {1} special character", message,  minAlpha);
                }

                this.ErrorMessage = message;
            }
                /* Validate against your provider and return true or false */
        }
    }

Usage:

[MembershipPasswordRequired]
internal string Password {get;set;}

The cool thing about this attribute is that you can decorate a property without specifying the ErrorMessage and it will build one dynamically from your default membership. Of course, you can change this up if you’re using multiple providers by getting the key of the current provider. But, the project I’m working on will always only have one provider, so this is how I’ll leave it.

A caveat: You can only set the ErrorMessage property once. If you try to assign to it more than once, you will receive an exception telling you this.

I won’t post the code for validating against the provider, because there are a number of ways to do this. Probably the safest way to do so is to use regex validation and pull that property from the provider’s parameters and just return whether the regex matches the string or not.

Anyway, I thought this was a pretty cool usage of DataAnnotations, and hooking it up on a custom CreateUser control was trivial with the DataAnnotation validator (from a few posts ago).

Flattr this!

System.ComponentModel.DataAnnotations for ASP.NET Web Forms

Although I’m primarily an ASP.NET Web Forms developer, I regularly dabble in new and interesting technologies.  I’ve toyed with other Microsoft technologies such as ASP.NET MVC and Dynamic Data web sites.

ASP.NET MVC offers an interesting mechanism for validating view models called DataAnnotations.   Examples can be seen here and here.

Some of the more useful attributes for validation include:

  • RequiredAttribute
  • RegularExpressionAttribute
  • RangeAttribute
  • DataTypeAttribute

I recently decided to implement a data validation schema (for lack of a better term) for web forms similar to that of ASP.NET MVC. This would allow us to maintain validation of a model object via attributes at the class level, instead of dispersing these validation rules through the web form code or any of the business logic layers. However, there will be occasions where an object’s validity depends upon some state or validity of another object. I’ve handled this by allowing the validation method to accept any action to be called after the object has been validated.

In order to make a domain object validatable, I’m going to implement the following interface:

IValidatable.cs

namespace Validatable
{
    interface IValidatable
    {
        System.Type EntityType { get; set; }
        System.Collections.Generic.List<object> Errors { get; set; }

        /// <summary>
        /// Determine whether the object is valid.  If invalid, errors are added to item.Errors
        /// </summary>
        /// <returns>true if valid, false if invalid</returns>
        bool IsValid();

        /// <summary>
        /// Validate this item against a supplied action
        /// </summary>
        /// <param name="action">The action to use for validation</param>
        void Validate(System.Action action);

        /// <summary>
        /// Validate this object against a Repository.
        /// <example>
        /// Item a = new Item();
        /// a.Validate(new ItemRepository());
        /// </example>
        /// Note: Repository must have a Validate(T item) method
        /// </summary>
        /// <param name="repository">The Repository to use for validation</param>
        void Validate(object repository);
    }
}

As you can see, this abstract class adds a property accessor for the entity’s type, a list of validation errors, an IsValid method, and two Validate methods.

Validatable<T>

I’ll take the code in chunks, since there is a lot more than I usually post.
First of all, the using directives required for this class are pretty sparse:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Reflection;

The class definition is:

   [Serializable]
    public abstract class Validatable<T> : IValidatable where T : class, new()
    { /* class */ }

If you’re unfamiliar with generic constraints, the where T : class, new() above enforces the T passed as in to be a class and to have a parameterless constructor (new())

The properties can be auto-implemented properties, or they can implement any backing logic you prefer. The constructor as I have it is:

 protected Validatable()
 {
     Errors = new List<object>();
     EntityType = typeof(T);
 }

Now for the methods and a slight explanation of each:

IsValid()

        public virtual bool IsValid()
        {
            Errors = new List<object>();
            PropertyInfo[] props = this.GetType().GetProperties();

            foreach (PropertyInfo property in props)
            {
                foreach (ValidationAttribute va in
                    property.GetCustomAttributes(true).OfType<ValidationAttribute>())
                {
                    var value = property.GetValue(this, null);
                    if (!va.IsValid(value))
                    {
                        Errors.Add(va.ErrorMessage);
                    }
                }
            }

            return Errors.Count <= 0;
        }

As a side note, all DataAnnotation attributes inherit from ValidationAttribute. You can create your own Validation Attributes by inheriting from this class. This method clears the list of errors and repopulates it by looping over any properties with validation attributes of this object, validates that property’s value against the attribute, and adds the ErrorMessage associated with it to the list of Errors.

Validate Methods

        public virtual void Validate(Action action)
        {
            if (IsValid())
            {
                action();
            }
        }

        public virtual void Validate(object repository)
        {
            MethodInfo method = repository.GetType().GetMethods()
                .Where(x => x.Name.Equals("Validate")).FirstOrDefault();
            if (method != null)
            {
                object[] parameters = new object[] { this };
                Validate(() => method.Invoke(repository, parameters));
            }
        }

These two methods can be changed to throw an exception if the object is invalid. I’ll leave that up to you. The way these are set up is to allow you to validate the object and perform either some unknown action or call Validate(T item) against some other object, arbitrarily called a repository. In actuality, you could have a Validate method on some other object that takes an object of this type and essentially chain validations.

The simplicity of the Validate(Action action) method is what makes it beautiful. For instance, you can have an item (a) and cause it save after validation by doing something like:

a.Validate(() => new ItemDAL().Save(a));

As you can see, a Save method in your Item’s Data Access Layer taking Item as a parameter can be called only when a.IsValid() is true. Again, there are a number of ways to tweak this and change it to your liking, but I’ll leave that up to you.

DataAnnotationValidator

Here is the wonderful part about all of this. You can create a custom validator that validates in a similar way as the Validatable class. I’ll post the code and quickly explain what it does. I got the idea from this from another blog and tweaked it a little.

DataAnnotationValidator.cs

// DataAnnotationValidator.cs
namespace Validatable
{
    using System;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Reflection;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    [ToolboxData("<{0}:DataAnnotationValidator runat=\"server\" ControlToValidate=\"[Required]\" Display=\"Dynamic\" Text=\"*\" SourceTypeName=\"[FullyQualifiedTypeName]\" PropertyToValidate=\"[PropertyName]\" />")]
    public class DataAnnotationValidator : BaseValidator
    {
        /// <summary>
        /// THe Property that should be checked
        /// </summary>
        public string PropertyToValidate { get; set; }

        /// <summary>
        /// The object's type
        /// </summary>
        public string SourceTypeName { get; set; }

        protected override bool EvaluateIsValid()
        {
            Type source = GetValidatedType();
            PropertyInfo property = GetValidatedProperty(source);
            string value = GetControlValidationValue(ControlToValidate);

            foreach (ValidationAttribute va in property
                .GetCustomAttributes(typeof(ValidationAttribute), true)
                .OfType<ValidationAttribute>())
            {
                if (!va.IsValid(value))
                {
                    if (string.IsNullOrEmpty(ErrorMessage))
                    {
                        this.ErrorMessage = va.ErrorMessage;
                    }
                    return false;
                }
            }

            return true;
        }

        private Type GetValidatedType()
        {
            if (string.IsNullOrEmpty(SourceTypeName))
            {
                throw new InvalidOperationException("Null SourceTypeName can't be validated");
            }

            Type validatedType = Type.GetType(SourceTypeName);
            if (validatedType == null)
            {
                throw new InvalidOperationException(
                    string.Format("{0}:{1}", "Invalid SourceTypeName", SourceTypeName));
            }

            return validatedType;
        }

        private PropertyInfo GetValidatedProperty(Type source)
        {
            PropertyInfo property = source.GetProperty(PropertyToValidate,
              BindingFlags.Public | BindingFlags.Instance);

            if (property == null)
            {
                throw new InvalidOperationException(
                  string.Format("{0}:{1}", "Validated Property Does Not Exists", PropertyToValidate));
            }
            return property;
        }
    }
}

This creates a validator web control which has ‘PropertyToValidate’ and ‘SourceTypeName’. When a Validator web control is added to a page, it must have ControlToValidate, PropertyToValidate, and SourceTypeName specified or an error will be thrown. The validation method verifies the type and the property, gets the value of the property and finally, much like the Validatable abstract class, it loops over all ValidationAttributes and validates the value against that attribute. You can use this with multiple attributes, so it doesn’t hurt to add this validator to a property– that just means you can add an attribute in the future and everything is already wired up! That’s pretty cool.

Example

As an example, I’m going to create a single page to **input** a Customer object. The customer object is very simple:

 public class Customer : Validatable.Validatable<Customer>
    {
        [Required(ErrorMessage="UserId is Required")]
        public int UserId { get; set; }

        [DataType(DataType.PhoneNumber, ErrorMessage="Invalid Phone Number")]
        public string PhoneNumber { get; set; }

        [RegularExpression(@"(^\d{5}(-\d{4}){0,1}$)", ErrorMessage="Invalid Zip Code")]
        public string ZipCode { get; set; }
    }

And the Page in full is collapsed below:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Example._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:Label ID="lblStatus" runat="server" />
    <asp:ValidationSummary ID="ValidationSummary1" runat="server" />
    <div>
        <asp:FormView ID="FormView1" runat="server" DataSourceID="srcRepository" 
            Width="119px" AllowPaging="True">
            <EditItemTemplate>
                UserId:
                <asp:TextBox ID="UserIdTextBox" runat="server" Text='<%# Bind("UserId") %>' />
                <example:DataAnnotationValidator ID="DataAnnotationValidator1" runat="server" ControlToValidate="UserIdTextBox" Display="Dynamic"
                    PropertyToValidate="UserId" ErrorMessage="Invalid User Identification Number" 
                    SourceTypeName="Example.Customer, Example, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" 
                    Text="*"/>
                <br />
                PhoneNumber:
                <asp:TextBox ID="PhoneNumberTextBox" runat="server" 
                    Text='<%# Bind("PhoneNumber") %>' />
                <example:DataAnnotationValidator ID="DataAnnotationValidator2" runat="server" ControlToValidate="PhoneNumberTextBox" Display="Dynamic"
                    PropertyToValidate="PhoneNumber" OnInit="GetTypeName" SourceTypeName="Example.Customer, Example, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" Text="*"/>
                <br />
                ZipCode:
                <asp:TextBox ID="ZipCodeTextBox" runat="server" Text='<%# Bind("ZipCode") %>' />
                <example:DataAnnotationValidator ID="DataAnnotationValidator3" runat="server" ControlToValidate="ZipCodeTextBox" Display="Dynamic"
                    PropertyToValidate="ZipCode" SourceTypeName="Example.Customer, Example, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" Text="*"/>
                <br />
                EntityType:
                <asp:TextBox ID="EntityTypeTextBox" runat="server" 
                    Text='<%# Eval("EntityType") %>' />
                <br />
                <asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" 
                    CommandName="Update" Text="Update" />
                &nbsp;<asp:LinkButton ID="UpdateCancelButton" runat="server" 
                    CausesValidation="False" CommandName="Cancel" Text="Cancel" />
            </EditItemTemplate>
            <InsertItemTemplate>
                UserId:
                <asp:TextBox ID="UserIdTextBox" runat="server" Text='<%# Bind("UserId") %>' />
                <example:DataAnnotationValidator ID="DataAnnotationValidator1" runat="server" ControlToValidate="UserIdTextBox" Display="Dynamic"
                    PropertyToValidate="UserId"  OnInit="GetTypeName"  Text="*"/>
                <br />
                PhoneNumber:
                <asp:TextBox ID="PhoneNumberTextBox" runat="server" 
                    Text='<%# Bind("PhoneNumber") %>' />
                <example:DataAnnotationValidator ID="DataAnnotationValidator2" runat="server" ControlToValidate="PhoneNumberTextBox" Display="Dynamic"
                    PropertyToValidate="PhoneNumber" OnInit="GetTypeName"  Text="*"/>
                <br />
                ZipCode:
                <asp:TextBox ID="ZipCodeTextBox" runat="server" Text='<%# Bind("ZipCode") %>' />
                <example:DataAnnotationValidator ID="DataAnnotationValidator3" runat="server" ControlToValidate="ZipCodeTextBox" Display="Dynamic"
                    PropertyToValidate="ZipCode" OnInit="GetTypeName"  Text="*"/>
                <br />
                EntityType:
                <asp:TextBox ID="EntityTypeTextBox" runat="server" 
                    Text='<%# Eval("EntityType") %>' />
                <br />
                <asp:LinkButton ID="InsertButton" runat="server" CausesValidation="True" 
                    CommandName="Insert" Text="Insert" />
                &nbsp;<asp:LinkButton ID="InsertCancelButton" runat="server" 
                    CausesValidation="False" CommandName="Cancel" Text="Cancel" />
            </InsertItemTemplate>
            <ItemTemplate>
                UserId:
                <asp:Label ID="UserIdTextBox" runat="server" Text='<%# Bind("UserId") %>' />
                <br />
                PhoneNumber:
                <asp:Label ID="PhoneNumberTextBox" runat="server" 
                    Text='<%# Bind("PhoneNumber") %>' />
                <br />
                ZipCode:
                <asp:Label ID="ZipCodeTextBox" runat="server" Text='<%# Bind("ZipCode") %>' />
                <br />
                EntityType:
                <asp:Label ID="EntityTypeLabel" runat="server" 
                    Text='<%# Bind("EntityType") %>' />
                <br />
                <asp:LinkButton ID="EditButton" runat="server" CausesValidation="False" 
                    CommandName="Edit" Text="Edit" />
                &nbsp;<asp:LinkButton ID="NewButton" runat="server" CausesValidation="False" 
                    CommandName="New" Text="New" />
            </ItemTemplate>
        </asp:FormView>
        <asp:ObjectDataSource ID="srcRepository" runat="server" 
            DataObjectTypeName="Example.Customer" InsertMethod="Save" 
            oninserted="srcRepository_Saved" onupdated="srcRepository_Saved" 
            SelectMethod="Get" TypeName="Example.CustomerRepository" UpdateMethod="Save"></asp:ObjectDataSource>
    </div>
    </form>
</body>
</html>

Of particular note here is in the EditTemplate, you’ll see

                  UserId:
                <asp:TextBox ID="UserIdTextBox" runat="server" Text='<%# Bind("UserId") %>' />
                <example:DataAnnotationValidator ID="DataAnnotationValidator1" runat="server" ControlToValidate="UserIdTextBox" Display="Dynamic"
                    PropertyToValidate="UserId" ErrorMessage="Invalid User Identification Number" 
                    SourceTypeName="Example.Customer, Example, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" 
                    Text="*"/>

in which the SourceTypeName must be the full Assembly Qualified Name. This is necessary if the Validatable and DataAnnotationValidator classes are in an external library. This is a rather tedious property to fill for each validator. Another way to get around this is to populate the SourceTypeName as seen in the InserItemTemplate, e.g.

                UserId:
                <asp:TextBox ID="UserIdTextBox" runat="server" Text='<%# Bind("UserId") %>' />
                <example:DataAnnotationValidator ID="DataAnnotationValidator1" runat="server" ControlToValidate="UserIdTextBox" Display="Dynamic"
                    PropertyToValidate="UserId"  OnInit="GetTypeName"  Text="*"/>

and the code in the code behind is very simple:

        protected void GetTypeName(object sender, EventArgs e)
        {
            DataAnnotationValidator validator = (DataAnnotationValidator)sender;
            validator.SourceTypeName = new Customer().EntityType.AssemblyQualifiedName;
        }

Also notice that the first validator (the one with the assembly qualified name) has an ErrorMessage property specified. Doing this allows you to override the error message returned from the validated object. We can do this if the model says “UserId” and you want the user to see this property referred to as “User Identification”.

Conclusion

Sometimes dabbling in other technologies can open the door for new and simpler ways of doing things. I like this example because it allows you to build web applications quickly and easily, while making them maintainable in the future (new validations only have to be added to the model, not to every control where the model must be validated).

For further reference, this project is linked below. Please download and modify if necessary.
Validatable.zip

Flattr this!

Finding a user’s local time from UTC offset

I answered a question over at StackOverflow, and I really liked the answer, so I thought I would share this nifty extension method:


        /// <summary>
        /// Convert a given DateTime object to a user's local time, 
        /// taking into account changes in TimeZone rules.
        /// For example, if you were to perform this operation on 
        /// a time now, during EST Daylight Saving, and that time falls 
        /// outside the scope of Daylight Saving time, the rule will adjust accordingly.
        /// </summary>
        /// <param name="dateTime">The DateTime object</param>
        /// <param name="offset">offset from UTC</param>
        /// <returns>User's local time</returns>
        public static DateTime ConvertToLocalDateTime(this DateTime dateTime, int offset)
        {
            TimeZoneInfo destinationTimeZone = TimeZoneInfo.GetSystemTimeZones()
               .Where(x => x.BaseUtcOffset.Hours.Equals(offset)).FirstOrDefault();

            var rule = destinationTimeZone.GetAdjustmentRules().Where(x =>
                x.DateStart <= dateTime && dateTime <= x.DateEnd)
                .FirstOrDefault();

            TimeSpan baseOffset = TimeSpan.Zero;
            if (rule != null)
            {
                baseOffset -= destinationTimeZone.IsDaylightSavingTime(dateTime) ?
                    rule.DaylightDelta : TimeSpan.Zero;
            }

            DateTimeOffset dto = DateTimeOffset.Parse(dateTime.ToString());
            return new DateTime(TimeZoneInfo
                     .ConvertTimeFromUtc(dateTime, 
                            destinationTimeZone).Ticks + baseOffset.Ticks);
        }

The summary basically says it all. I ran through a couple of tests with this, I’d like to know if anyone uses this and makes modifications to it!

Flattr this!