Validation in ASP.NET MVC – part 4: example with server-side and client-side validation

This is part 4 of a series of posts. See also:

In the previous posts, I described how we implemented model-based validation on the server-side in Cuyahoga with ASP.NET MVC and as the icing on the cake, we also added some client-side validation (also model-based).

Now, everything can be found in the Cuyahoga SVN sources but I have to agree that it can be a daunting task to check out the complete sources and find all pieces of the validation puzzle. Therefore, I’ve created a little sample application with everything from the previous posts combined.

validation-sample-app

Hopefully, this will make things a little bit clearer. You can download the sample app here. Visual Studio 2008 and ASP.NET MVC Beta are required.

Enjoy!

Validation in ASP.NET MVC – part 3: client-side validation with jquery validation

This is part 3 of a series of posts. See also:

In the first two parts, I showed how you can perform validation on the server side with Castle Validation attributes and extend that model with custom validation logic. With this, we have everything we need to properly validate our model.

For a better user experience though, it would also be nice that we could re-use (part of) our validation logic on the client-side. Luckily, lots of others have already looked into this and the only thing I had to do was to throw everything together and stir it a little bit :) .

The ingredients are:

How it works

client-side-validation-1

  1. The client-side validation is called via an HtmlHelper extension method ClientSideValidation:
    <%= Html.ClientSideValidation(ViewData.Model, “my_form_id”)%>;
  2. The HtmlHelper extension requests an instance of a BrowserValidationEngine that returns the client script for validation;
  3. BrowserValidationEngine has a reference to an IValidatorRegistry instance that returns all (Castle) validators for the given model;
  4. For each validator, the referenced IBrowserValidatorProvider generates the appropriate client script;
  5. Finally, all generated client script code is combined and sent to the browser in a single javascript block.

The existing Monorail codebase proved to be of great value and could be used almost seamlessly. The only difference is the way the client code is generated. Originally, the validators generated css class attributes for the Monorail form helpers, but we don’t have those with ASP.NET MVC, so all client code is generated as jQuery validation rules.

Below, you can see the output of the validation helper for the new user form in Cuyahoga:

<script type="text/javascript">
$(document).ready(function() {
    jQuery.validator.addMethod('notEqualTo', function(value, element, param) { return value != jQuery(param).val(); }, 'Must not be equal to {0}.' );
    jQuery.validator.addMethod('greaterThan', function(value, element, param) { return ( IsNaN( value ) && IsNaN( jQuery(param).val() ) ) || ( value > jQuery(param).val() ); }, 'Must be greater than {0}.' );
    jQuery.validator.addMethod('lesserThan', function(value, element, param) { return ( IsNaN( value ) && IsNaN( jQuery(param).val() ) ) || ( value < jQuery(param).val() ); }, 'Must be lesser than {0}.' );
    jQuery.validator.addMethod('numberNative', function(value, element, param) { return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:\,\d+)?$/.test(value); }, 'Not a valid number.' );
    jQuery.validator.addMethod('simpleDate', function(value, element, param) { return this.optional(element) || /^\d{1,2}\-\d{1,2}\-\d{4}$/.test(value); }, 'Not a valid date.' );
    $("#userform").validate({
        rules : {
            UserName: {  rangelength: [1, 50] , required: true },
            Password: {   required: true , rangelength: [5, 50] , equalTo: "#PasswordConfirmation" },
            PasswordConfirmation: {   equalTo: "#Password" , rangelength: [5, 50] , required: true },
            FirstName: { rangelength: [1, 100] },
            LastName: { rangelength: [1, 100] },
            Email: {   required: true , rangelength: [1, 100] , email: true },
            Website: { rangelength: [1, 100] }
        },
        messages : {
            UserName: {  rangelength: "The username must be between 1 and 50 characters" , required: "The username may not be empty" },
            Password: {   required: "The password may not be empty" , rangelength: "The password must contain at least 5 characters" , equalTo: "The password must be the same as the confirmation password" },
            PasswordConfirmation: {   equalTo: "The password must be the same as the confirmation password" , rangelength: "The password must contain at least 5 characters" , required: "The password confirmation may not be empty" },
            FirstName: { rangelength: "The firstname must be between 1 and 100 characters" },
            LastName: { rangelength: "The lastname must be between 1 and 100 characters" },
            Email: {   required: "E-mail address may not be empty" , rangelength: "E-mail address must be between 1 and 100 characters" , email: "Invalid e-mail address" },
            Website: { rangelength: "The website url must be between 1 and 100 characters" }
        }
    });
});
</script>

which results in this:

client-side-validation-2

Summarizing validation

In this series of posts, I showed how we deal with validation in Cuyahoga and ASP.NET MVC. Personally, I think the nicest part of it is that we have our validation rules centralized and we only have to add one line of code to the view to enable client-side validation.

The code can be found in Cuyahoga SVN and more specifically in the validation sections and the ASP.NET MVC manager. I’ll try to make a standalone sample project with all the validation stuff somewhere in the near future.

Embrace the impedance mismatch

Maybe I’m a bit of a masochist, but I enjoy a good flamewar at times. For that reason, I still have TheServerSide.com in my bookmarks to check out what our Java friends are bitching about. My favorite subjects are ‘the new web framework of the month’ and the occasional persistence framework rants. Today, I checked TheServerSide to see a post with the subject “Criticism of Java Persistence Frameworks” that had a promising 46 comments. Yummie!

The comments were a little bit disappointing for my taste, but one from Robert Pappas was very interesting:

The gap between stateless HTTP and OOP is nearly as wide as the gap between OOP and RDMS.
This is why we have at least 6 major Web Frameworks for Java…and all of them have serious drawbacks (from my experience anyway).
But yes, your concerns are valid. There is a mis-match, and I’m not sure if it can be address in a seamless way. (Without switching to Object Databases)

And he’s right! The impedance mismatch that people often talk about, also exists in web programming. So instead of one impedance mismatch we have to deal with at least two of them! That makes a developers life even worse, according to the rest of the comment.

holygrailWhat struck me about this comment is the negative tone that might have been caused by frustrations when trying to bridge the gaps between relational databases, OO and web programming. Lots of developers are constantly searching for the one and only Holy Grail of Software Development and get frustrated when it appears that what they found is all but the Holy Grail.

Embrace it

One day, I came to the conclusion that the Holy Grail of Software Development doesn’t exist and that made developing software so much more fun. It’s just the mind set! Accept it and embrace it, stop searching for the Holy Grail and use the tools that help to embrace the mismatch instead of fighting it.

Back to .NET web application development: choose a good O/R mapping solution and something like ASP.NET MVC or Monorail. Definitely not the Holy Grail, but these tools embrace the impedance mismatch and that sure made development less frustrating and much more fun!

Hidden jewels in the Castle stack: Transaction Services

In Cuyahoga, we’re using a lot of components from the Castle stack. Some of the most brilliant components are the transaction services combined with the automatic transaction facility.

With this post, I’m trying to bring some well-deserved attention to these undervalued components.

The Context

Today, I was working on management of sites. In Cuyahoga 2.0, every site has its own set of content folders and templates. Now when creating a new site, we have to perform the following steps:

  1. Save the new site object in the database;
  2. Create a folder structure for the new site;
  3. Copy the selected system template objects to the new site and save in the database;
  4. Copy the template files that belong to the copied template objects to the templates folder of the site.

All steps have to be completed before we can start management of the new site, like adding pages and custom templates. Obviously, you’d like this series of steps to be completed  in a single transaction, so when something goes wrong somewhere, we don’t end up with a broken site.

As you might have noticed, the transaction also includes file operations and we all have probably experienced situations where the database and the file system were out of sync because something went wrong, either in the database, or with the file system.

Enter Castle Transactions

Castle Transaction Services makes it possible to run any arbitrary piece of code within the scope of a transaction. Components that are called in a transaction can support those transactions by requesting the current transaction via a transaction manager. This makes it very easy to write your own components that are transaction-aware.

Transactional file operations: don’t let the database and file system go out of sync

For file operations, we created a simple service that performs common file operations like writing new files, copying files and creating folders. When performing an operation, the service checks if there is a current transaction and if so, the actual operation is delegated to a class that performs the actual transactional operation. An excerpt of our transactional fileservice:

public void CopyFile(string filePathToCopy, string directoryToCopyTo)
{
    ITransaction transaction = ObtainCurrentTransaction();
    if (transaction != null)
    {
        FileWriter fileWriter = new FileWriter(this._tempDir, transaction.Name);
        transaction.Enlist(fileWriter);
        fileWriter.CopyFile(filePathToCopy, directoryToCopyTo);
    }
    else
    {
        File.Copy(filePathToCopy, Path.Combine(directoryToCopyTo, Path.GetFileName(filePathToCopy)), true);
    }
}

In the example above, the FileWriter class performs the transactional file operations by implementing an IResource interface that has three methods: Start(), RollBack() and Commit(). The CopyFile() method copies the file to a temporary location. When the transaction manager commits the transaction, the Commit() method of the FileWriter is called and the file is copied from the temporary location to the actual location. RollBack() removes the temporary file.

The complete implementation of the file service can be found in Cuyahoga SVN at https://cuyahoga.svn.sourceforge.net/svnroot/cuyahoga/trunk/Core/Service/Files. Note that the implementation is very basic and there’s much room for improvement but it already saved us lots of time when we didn’t have to clean up the mess when something went wrong.

Automatic transactions

One of the really great features of the Castle transaction services is that you just have to decorate your method with an attribute and everything is executed within the context of a transaction:

[Transaction(TransactionMode.RequiresNew)]
public virtual void CreateSite(Site site, string siteDataRoot, IList<Template> templatesToCopy, string systemTemplatesDirectory)
{
    // 1. Save new site object in the database.
    ..

    // 2. Create site directories.
    ..

    // 3. Copy template objects to new site and save in database.
    ..

    // 4. Copy template files to site templates directory.
    ...
}

Validation in ASP.NET MVC – part 2: custom server-side validation

This is a post in a series of posts. See also:

In the first post of this series, I showed how you can perform basic server-side validation on your model with help of the Castle Validator component. To summarize this post: the controller validates an object that is decorated with validation attributes with the help of an IModelValidator component and adds errors to the ModelState.

The first reason to abstract the validator was to prevent coupling of MVC controllers to the Castle Validators. But the abstraction also provides a very nice extension point. We can inject any kind of validator into the controller constructor as long as it implements the IModelValidator interface:

public LoginController(IAuthenticationService authenticationService, IModelValidator<LoginViewData> modelValidator)
{
    this._authenticationService = authenticationService;
    this.ModelValidator = modelValidator;
}

In the example above, the constructor requires an IModelValidator<LoginViewData> instance. In our case, Castle Windsor injects a CastleModelValidator<LoginViewData> instance that is registered in the container for IModelValidator<T>. We’re already seeing the first extension: the IModelValidator interface has a generic inheritor.

Extending the ModelValidator

In many scenario’s, property validation with the generic CastleModelValidator<T> will suffice, but sometimes you’ll need some extra validation. For example, when creating a new user, we want to check if the username doesn’t already exist. To perform this check, we created a UserModelValidator class that inherits CastleModelValidator<T>.

validation-custom

The CastleModelValidator<T> calls a virtual method PerformValidation() while validating via IsValid(). In UserModelValidator, this method is overriden and performs the check if the username is unique:

public class UserModelValidator : CastleModelValidator<User>
{
    private readonly IUserService _userService;

    public UserModelValidator(IUserService userService)
    {
        _userService = userService;
    }

    protected override void PerformValidation(User objectToValidate, ICollection<string> includeProperties)
    {
        // First validate the property values via the Castle validator.
        base.PerformValidation(objectToValidate, includeProperties);

        // Check username uniqueness.
        if (ShouldValidateProperty("UserName", includeProperties)
            && ! String.IsNullOrEmpty(objectToValidate.UserName))
        {
            if (this._userService.FindUsersByUsername(objectToValidate.UserName).Count > 0)
            {
                AddError("UserName", "UserNameValidatorNotUnique", true);
            }
        }
    }
}

Because the modelvalidators are registered in the Windsor Container, we can inject any kind of service or data access component into the validator and thus making it very easy to perform custom validation logic that needs to check the database, or check an external web service.

Tying things together

We want the UsersController to use the custom UserModelValidator when ValidateModel() is called. All we have to do is to add UserModelValidator to the constructor of the controller and we’re done:

public UsersController(IUserService userService, UserModelValidator userModelValidator)
{
    this._userService = userService;
    this.ModelValidator = userModelValidator;
}

Finally, this is how it looks in the browser. Nice to see the custom validation error nicely integrated with the rest of the errors.

image

Other extension possibilities

In this post we’ve seen an example where we extended our CastleModelValidator<T> to perform custom logic by calling another service. You might as well call a method on the object itself that is validated to perform custom business logic:

protected override void PerformValidation(MyClass objectToValidate, ICollection<string> includeProperties)
{
    base.PerformValidation(objectToValidate, includeProperties);

    if (! objectToValidate.CheckThatMyBizarreBusinessRuleIsValid())
    {
        AddError("MyProperty", "The object to validate is invalid.");
    }
}

You can also opt for plugging in a completely different library. CSLA fans can very easily implement their own version of IModelValidator<T>, or you could write an IModelValidator<T> implementation that uses the Validation Application Block from Enterprise Library.

The code

This is a series of posts that is directly inspired by Cuyahoga development. All code can be found in the Cuyahoga SVN trunk at https://cuyahoga.svn.sourceforge.net/svnroot/cuyahoga/trunk. The validation stuff sits in the Validation subdirectory of Cuyahoga.Core: https://cuyahoga.svn.sourceforge.net/svnroot/cuyahoga/trunk/Core/Validation. Note that Cuyahoga is work in progress. It’s not guaranteed that the code in SVN will be exactly the same as the sample code in this post.

Validation in ASP.NET MVC – part 1: basic server-side validation

Almost every single application has to deal with validating user input. With web applications, you can choose to do the validation on the client side or on the server side. In my opinion, validation should at least take place on the server side and optionally on the client side to improve the user experience. Therefore, I’m starting this series of posts with the basic needs: server-side validation.
For some background, also check the excellent post about validation by Steve Sanderson.

Validate the model and not the UI

In the past I used the ASP.NET WebForms validators. These do a proper job, but are also very much tied to the individual pages, so you have the validation logic scattered all over the place. For Cuyahoga 2, I really wanted a better solution where validation logic is centralized in the model (and removed from the UI layer).
There are already several solutions that make this possible. Microsoft PnP released the validation application block and recently (.NET 3.5 SP1), we have the DataAnnotations from ASP.NET Dynamic Data.

In Cuyahoga, we’re using the Castle Validator component to perform basic validation, mostly because we’re already using other components from the Castle stack and it just works fine. With Castle validators, you’re decorating properties of your Domain entities with attributes like:

[ValidateNonEmpty("UserNameValidatorNonEmpty")]
[ValidateLength(1, 50, "UserNameValidatorLength")]
public virtual string UserName
{
    get { return this._userName; }
    set { this._userName = value; }
}

Note that it’s also possible to decorate DTO’s or presentation models or whatever you want to call these data containers. In Cuyahoga for example, we have a LoginViewData class that is only used in the UI layer, that is also decorated with validator attributes. If we have a validation infrastructure we might as well (ab)use it :) .

IModelValidator

So how are we going to use the Castle validators with ASP.NET MVC?

First we have to make a decision where we want to validate the model. You can do this in the controller or in the service layer (if you one). Some people suggest doing validation in the data access layer but I think the responsibility of a data access layer is persisting and retrieving the model and nothing else.

I’ve chosen to validate the model from the controller because it’s a little bit more convenient as you don’t have to throw exceptions across layers and translate those exceptions to error messages for the user. For validation, all controllers inherit from a base controller that has a ValidateModel() method. This controller also has an instance of an IModelValidator interface to perform the actual validation, so we don’t pollute the controller too much with validation logic and also prevent coupling to a specific implementation.

validation-controller

At this point, the controller can validate, but to use the Castle validators we have to implement IModelValidator and pass that to the controller. But first: a base controller doesn’t know which type to validate, but a concrete controller does (assuming we’re only validating one concrete type in a controller) and therefore we created the IModelValidator<T> interface. The CastleModelValidator<T> class implements this interface.

Because we’re using the Castle Windsor IoC container we can wire everything together in the controller constructor:

public class LoginController : BaseController
{
    private readonly IAuthenticationService _authenticationService;
    /// <summary>
    /// Create and initialize an instance of the LoginController class.
    /// </summary>
    /// <param name="authenticationService">The authentication service</param>
    /// <param name="modelValidator">The IModelValidator for LoginViewData</param>
    public LoginController(IAuthenticationService authenticationService, IModelValidator<LoginViewData> modelValidator)
    {
        this._authenticationService = authenticationService;
        this.ModelValidator = modelValidator;
    }
}

In the container is the registered that when asked for an instance of IModelValidator<T>, the container should return an instance of CastleModelValidator<T>. The constructor in the code above, receives an instance of CastleModelValidator<LoginViewData>and sets the ModelValidator of the base controller.

How it works: the login screen

The Login action of the LoginController performs validation after populating a LoginViewData instance via TryUpdateModel():

public ActionResult Login(string returnUrl)
{
    var loginUser = new LoginViewData();
    try
    {
        if (TryUpdateModel(loginUser) && ValidateModel(loginUser))
        {
             // do authentication and exception handling

ValidateModel() automatically adds all errors to the ASP.NET MVC ModelState, so we have to do very little to actually display the validation errors:

login

The code

This is a series of posts that is directly inspired by Cuyahoga development. All code can be found in the Cuyahoga SVN trunk at https://cuyahoga.svn.sourceforge.net/svnroot/cuyahoga/trunk. Please note that all ASP.NET MVC stuff sits in the Manager subdirectory of the Cuyahoga.Web: https://cuyahoga.svn.sourceforge.net/svnroot/cuyahoga/trunk/Web/Manager.

A new experiment

Last week, I started to do some serious Cuyahoga development again and I’m going to try a new development methodology: blog-driven-development. A few days of development brought up so many interesting things, so I decided that I might as well write about them (in fact, I already started it because this post was also triggered by Cuyahoga development).

In the near future, I’ll be writing about the following topics:

  • adding an ASP.NET MVC application to your legacy Webforms application;
  • running the same legacy application in IIS 7.0 integrated mode;
  • a multi-part post about validation with Castle validators and ASP.NET MVC;
  • any other interesting topic that comes up during development.

NHibernate criteria queries across multiple many-many associations

Recently, I ran into an issue with NHibernate Criteria queries. The scenario is the following:

double-many-many

User has a many-many association with Role and Role has a many-many association with Site. I simply wanted all users that belong to a given site (and a whole slew of other optional parameters, therefore the Criteria query).

With hql this is simple:

select distinct u from User u join u.Roles r join r.Sites s where s.Id = :siteId

With a criteria query, it appeared a little bit harder. First I tried this:

ICriteria crit = session.CreateCriteria(typeof(User))
    .CreateCriteria("Roles") // traverse into Roles
        .CreateCriteria("Sites") // traverse into Sites
            .Add(Expression.Eq("Id", siteId);

Note the absence of the distinct keyword anywhere in the query. A nice Cartesian Product was the result due to the joins on the linking tables. Some googling showed that we can get distinct results with Criteria queries by applying the DistinctRootEntityResultTransformer via Criteria.SetResultTransformer() but that all happens in memory and not in the database query (call me old-fashioned, but I’d like my database results properly filtered :) ).

Finally, I found the solution in using subqueries:

ICriteria crit = session.CreateCriteria(typeof(User));

DetachedCriteria roleIdsForSite = DetachedCriteria.For(typeof (Role))
    .SetProjection(Projections.Property("Id"))
    .CreateCriteria("Sites", "site")
    .Add(Expression.Eq("site.Id", siteId.Value));

DetachedCriteria userIdsForRoles = DetachedCriteria.For(typeof(User))
    .SetProjection(Projections.Distinct(Projections.Property("Id")))
    .CreateCriteria("Roles")
        .Add(Subqueries.PropertyIn("Id", roleIdsForSite));

crit.Add(Subqueries.PropertyIn("Id", userIdsForRoles));

Yes, that’s an insane amount of code to do something that simple, but it works and the generated SQL is highly efficient :) . Notice the distinct projection in the second DetachedCriteria (userIdsForRoles).

I’d really appreciate it if somebody has any suggestions for improvement.

Paging with ASP.NET MVC

Updated 2009-02-04: Upgraded source and demo to ASP.NET MVC RC1

Updated 2009-01-16: Upgraded source and demo to ASP.NET MVC Beta

Updated 2008-09-09: Source and Demo now use ASP.NET MVC preview 5

On my latest gig, we used ASP.NET MVC and it was a very pleasant experience! Very clean code, clean html output and the productivity was great (which is not very common when using a technology for the first time).

Of course, since ASP.NET MVC isn’t finished yet, it leaves something to desire. At one time we needed paging and there isn’t an out-of-the-box solution for it (yet). Some googling revealed that others had already addressed this, but to be honest, I wasn’t entirely pleased with the solutions, so I grabbed the best parts and build a generic solution out of it.

I’m in a hurry, take me to the download immediately

IPagedList<T>

First, there was the PagedList<T> that Scott Guthrie already used in one of the earliest MVC demo’s and that later appeared in improved incarnations from Rob Conery and  Troy Goode. This was a nice starting point, especially because we also used LINQ To SQL as our data access layer. To provide an extra extension point, I created an IPagedList<T> interface instead of using the PagedList<T> directly.

public interface IPagedList<T> : IList<T>
{
    int PageCount { get; }
    int TotalItemCount { get; }
    int PageIndex { get; }
    int PageNumber { get; }
    int PageSize { get; }
    bool HasPreviousPage { get; }
    bool HasNextPage { get; }
    bool IsFirstPage { get; }
    bool IsLastPage { get; }
}

Html.Pager()

After choosing the IPagedList<T> implementation I started thinking about how I could create an HtmlHelper extension method that renders the page links. First, I made the mistake to couple the helper to the IPagedList<T> and it took me a little while to realize that a paging HTML helper doesn’t need anything to know about the underlying data source. It’s sole purpose is to generate a list of hyperlinks for pages and the only thing we need to know is the total amount of items, the page size and the current page. This is what the most basic HtmlHelper extension looks like:

public static string Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount)

We’re assuming that the page links point to the the current controller and current action. Alternatively, it’s possible to supply a different action:

public static string Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount, string actionName)

Combining the Pager html helper and IPagedList<T> in a view page (that inherits from ViewPage<IPagedList<Product>>):

<table class="grid">
    <thead>
        <tr>
            <th>Product name</th>
            <th>Category</th>
        </tr>
    </thead>
    <tbody>
        <% foreach (var product in Model) { %>
            <tr>
                <td><%= product.Name %></td>
                <td><%= product.Category %></td>
            </tr>
        <% } %>
    </tbody>
</table>
<div class="pager">
    <%= Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount) %>
</div>

results in this:

aspnetmvc-pager

You probably recognize the digg-style appearance of the pager. Thanks to the ASP.NET MVC sample application KIGG for inspiration :) .

Internally, the pager uses RouteTable.Routes.GetVirtualPath() to render the url’s so the page url’s can be configured via routing to create nice looking url’s like for example ‘/Categories/Shoes/Page/1′ instead of ‘/Paging/ViewByCategory?name=Shoes&page=1′.

Advanced scenarios

Many scenarios where you want to use paging also use filtering. It’s possible to pass extra parameters to the Pager helper via a RouteValueDictionary or an anonymous type. This adds these parameters to the page links that are generated:

<div class="pager">
    <%= Html.Pager(ViewData.Model.PageSize, ViewData.Model.PageNumber, ViewData.Model.TotalItemCount, new { categoryname = ViewData["CategoryDisplayName"] } )%>
</div>

aspnetmvc-pager-2

That’s it. A complete solution with demo project can be downloaded below. Feel free to leave any comments or remarks. One of the things I’m not happy about is that I failed to properly unit test the pager, but that’s for a different post.

Download

Download the paging sample solution, incl. the demo MVC web project

Check also the AJAX version of the pager written by Daniel Iglesias: http://danieliglesiaseng.blogspot.com/2010/01/ajax-paging-with-aspnet-mvc.html.

Introduction

Hi, my name is Martijn Boland. For a living, I develop software and try to help other people building better software. Together with Erwin Berends, I own a little software company in the Netherlands called Taiga. I’m also the lead developer of the Cuyahoga CMS project.

In this blog, I’m mainly going to write about the technical stuff that I’m encountering on a day-to-day basis. Currently I’m especially interested in the things that ALT.NET adds to the Microsoft .NET environment, so you can expect some posts in that area.