Skip to content

Jimmy Bogard
Syndicate content
Strong opinions, weakly held
Updated: 1 hour 4 min ago

Conventional HTML in ASP.NET MVC: Data-bound elements

11 hours 18 min ago

Other posts in this series:

We’re now at the point where our form elements replace the existing templates in MVC, extend to the HTML5 form elements, but there’s still something missing. I skipped over the dreaded DropDownList, with its wonky SelectListItem objects.

Drop down lists can be quite a challenge. Typically in my applications I have drop down lists based on a few known sets of data:

  • Static list of items
  • Dynamic list of items
  • Dynamic contextual list of items

The first one is an easy target, solved with the previous post and enums. If a list doesn’t change, just create an enum to represent those items and we’re done.

The second two are more of a challenge. Typically what I see is attaching those items to the ViewModel or ViewBag, along with the actual model. It’s awkward, and combines two separate concerns. “What have I chosen” is a different concern than “What are my choices”. Let’s tackle those last two choices separately.

Dynamic lists

Dynamic lists of items typically come from a persistent store. An administrator goes to some configuration screen to configure the list of items, and the user picks from this list.

Common here is that we’re building a drop down list based on set of known entities. The definition of the set doesn’t change, but its contents might.

On our ViewModel, we’d handle this in our form post with an entity:

public class RegisterViewModel
{
    [Required]
    public string Email { get; set; }

    [Required]
    public string Password { get; set; }

    public string ConfirmPassword { get; set; }

    public AccountType AccountType { get; set; }
}

We have our normal registration data, but the user also gets to choose their account type. The values of the account type, however, come from the database (and we use model binding to automatically bind up in the POST the AccountType you chose).

Going from a convention point of view, if we have a model property that’s an entity type, let’s just load up all the entities of that type and display them. If you have an ISession/DbContext, this is easy, but wait, our view shouldn’t be hitting the database, right?

Wrong.

Luckily for us, our conventions let us easily handle this scenario. We’ll take the same approach as our enum drop down builder, but instead of using type metadata for our list, we’ll use our database.

Editors.Modifier<EnitityDropDownModifier>();

// Our modifier
public class EnitityDropDownModifier : IElementModifier
{
    public bool Matches(ElementRequest token)
    {
        return typeof (Entity).IsAssignableFrom(token.Accessor.PropertyType);
    }

    public void Modify(ElementRequest request)
    {
        request.CurrentTag.RemoveAttr("type");
        request.CurrentTag.TagName("select");
        request.CurrentTag.Append(new HtmlTag("option"));

        var context = request.Get<DbContext>();
        var entities = context.Set(request.Accessor.PropertyType)
            .Cast<Entity>()
            .ToList();
        var value = request.Value<Entity>();

        foreach (var entity in entities)
        {
            var optionTag = new HtmlTag("option")
                .Value(entity.Id.ToString())
                .Text(entity.DisplayValue);

            if (value != null && value.Id == entity.Id)
                optionTag.Attr("selected");

            request.CurrentTag.Append(optionTag);
        }
    }
}

Instead of going to our type system, we query the DbContext to load all entities of that property type. We built a base entity class for the common behavior:

public abstract class Entity
{
    public Guid Id { get; set; }
    public abstract string DisplayValue { get; }
}

This goes into how we build our select element, with the display value showed to the user and the ID as the value. With this in place, our drop down in our view is simply:

<div class="form-group">
    @Html.Label(m => m.AccountType)
    <div class="col-md-10">
        @Html.Input(m => m.AccountType)
    </div>
</div>

And any entity-backed drop-down in our system requires zero extra effort. Of course, if we needed to cache that list we would do so but that is beyond the scope of this discussion.

So we’ve got dynamic lists done, what about dynamic lists with context?

Dynamic contextual list of items

In this case, we actually can’t really depend on a convention. The list of items is dynamic, and contextual. Things like “display a drop down of active users”. It’s dynamic since the list of users will change and contextual since I only want the list of active users.

It then comes down to the nature of our context. Is the context static, or dynamic? If it’s static, then perhaps we can build some primitive beyond just an entity type. If it’s dynamic, based on user input, that becomes more difficult. Rather than trying to focus on a specific solution, let’s take a look at the problem: we have a list of items we need to show, and have a specific query needed to show those items. We have an input to the query, our constraints, and an output, the list of items. Finally, we need to build those items.

It turns out this isn’t really a good choice for a convention – because a convention doesn’t exist! It varies too much. Instead, we can build on the primitives of what is common, “build a name/ID based on our model expression”.

What we wound up with is something like this:

public static HtmlTag QueryDropDown<T, TItem, TQuery>(this HtmlHelper<T> htmlHelper,
    Expression<Func<T, TItem>> expression,
    TQuery query,
    Func<TItem, string> displaySelector,
    Func<TItem, object> valueSelector)
    where TQuery : IRequest<IEnumerable<TItem>>
{
    var expressionText = ExpressionHelper.GetExpressionText(expression);
    ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    var selectedItem = (TItem)metadata.Model;

    var mediator = DependencyResolver.Current.GetService<IMediator>();
    var items = mediator.Send(query);
    var select = new SelectTag(t =>
    {
        t.Option("", string.Empty);
        foreach (var item in items)
        {
            var htmlTag = t.Option(displaySelector(item), valueSelector(item));
            if (item.Equals(selectedItem))
                htmlTag.Attr("selected");
        }

        t.Id(expressionText);
        t.Attr("name", expressionText);
    });

    return select;
}

We represent the list of items we want as a query, then execute the query through a mediator. From the results, we specify what should be the display/value selectors. Finally, we build our select tag as normal, using an HtmlTag instance directly. The query/mediator piece is the same as I described back in my controllers on a diet series, we’re just reusing the concept here. Our usage would look something like:

<div class="col-md-10">
    @Html.QueryDropDown(m => m.User,
        new ActiveUsersQuery(),
        t => t.FullName,
        t => t.Id)
</div

If the query required contextual parameters – not a problem, we simply add them to the definition of our request object, the ActiveUsersQuery class.

So that’s how we’ve tackled dynamic lists of items. Depending on the situation, it requires conventions, or not, but either way the introduction of the HtmlTag library allowed us to programmatically build up our HTML without resorting to strings.

We’ve tackled the basics of building input/output/label elements, but we can go further. In the next post, we’ll look at building higher-level components from these building blocks that can incorporate things like validation messages.

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

Categories: Blogs

Conventional HTML in ASP.NET MVC: Replacing form helpers

Tue, 07/22/2014 - 17:51

Other posts in this series:

Last time, we ended at the point where we had a baseline behavior for text inputs, labels and outputs. We don’t want to stop there, however. My ultimate goal is to eliminate (as much as possible) using any specific form helper from ASP.NET MVC. Everything we need to determine what/how to render input elements is available to us on metadata, we just need to use it.

Our first order of business is to catalog the expected elements we wish to support:

  • Button (no)
  • Checkbox (yes)
  • Color (yes)
  • Date (yes)
  • DateTime (yes)
  • DateTime Local (yes)
  • Email (Yes)
  • File (No)
  • Hidden (Yes)
  • Image (No)
  • Month (No)
  • Number (Yes)
  • Password (Yes)
  • Radio (Yes)
  • Range (No)
  • Reset (No)
  • Search (No)
  • Telephone (Yes)
  • Text (Yes)
  • Time (Yes)
  • Url (Yes)

And the other two input types that don’t use the <input> element, <select> and <textarea>. This is where convention-based programming and the object model of HtmlTags really shines. Instead of us needing to completely replace a template as we do in MVC, we only need to extend the individual tags, and leave everything else alone. We know that we want to have a baseline style on all of our inputs. We also want to configure this once, which our HTML conventions allow.

So how do we want to key into our conventions? I like to follow a progression:

  • Member type
  • Member name
  • Member attributes

We can infer a lot from the type of a member. Boolean? That’s a checkbox. Nullable bool? That’s not a checkbox, but a select, and so on. Let’s look at each type of input and see what we can infer to build our conventions.

Labels

Labels can be a bit annoying, you might need localization and so on. What I’d like to do is provide some default, sensible behavior. If we look at a login view model:

public class LoginViewModel
{
    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [Display(Name = "Remember me?")]
    public bool RememberMe { get; set; }
}

We have a ton of display attributes, all basically doing nothing. These labels key into a couple of things:

  • Label text
  • Validation errors

We’ll get to validation in a future post, but first let’s look at the labels. What can we provide as sensible defaults?

  • Property name
  • Split PascalCase into separate words
  • Booleans get a question mark
  • Fallback to the display attribute if it exists

A sensible label convention would get rid of nearly all of our “Label” attributes. The default conventions get us the first two, we just need to modify for the latter two:

Labels.ModifyForAttribute<DisplayAttribute>((t, a) => t.Text(a.Name));
Labels.IfPropertyIs<bool>()
    .ModifyWith(er => er.CurrentTag.Text(er.OriginalTag.Text() + "?"));

With this convention, our Display attributes go away. If we have a mismatch between the view model property and the label, we can use the Display attribute to specify it explicitly. I only find myself using this when a model is flattened. Otherwise, I try and keep the label I show the users consistent with how I model the data behind the scenes.

Checkbox

This one’s easy. Checkboxes represent true/false, so that maps to a boolean:

Editors.IfPropertyIs<bool>().Attr("type", "checkbox");

// Before
@Html.CheckBoxFor(m => m.RememberMe)
@Html.LabelFor(m => m.RememberMe)

// After
@Html.Input(m => m.RememberMe)
@Html.Label(m => m.RememberMe)

Not very exciting, we just tell Fubu for bools, make the “type” attribute a checkbox. The existing MVC template does a few other things, but I don’t like any of them (like an extra hidden etc).

Color

With some model binding magic, we can handle this by merely looking at the type:

Editors.IfPropertyIs<Color>().Attr("type", "color");


Date/Time/DateTime/Local DateTime

This one is a little bit more difficult, since the BCL doesn’t have a concept of a Date. However, NodaTime does, so we can use that type and key off of it instead:

Editors.IfPropertyIs<LocalDate>().Attr("type", "date");
Editors.IfPropertyIs<LocalTime>().Attr("type", "time");
Editors.IfPropertyIs<LocalDateTime>().Attr("type", "datetime-local");
Editors.IfPropertyIs<OffsetDateTime>().Attr("type", "datetime");


Email

Email could go a number of different ways. There’s not really an Email type in .NET, so we can’t key off the property type. The MVC version uses an attribute to opt-in to an Email template, but I think that’s redundant. In my experience, every property with “Email” in the name is an email address. Why not key off this?

Editors.If(er => er.Accessor.Name.Contains("Email"))
    .Attr("type", "email");

This one could go both ways, but if I want to also/instead go off the DataType attribute, it’s just as easy. I don’t like being too explicit or too confusing, so you’ll have to base this on what you actually find in your systems.

Hidden

Hiddens can be a bit funny. If I’m being sensible with Guid identifiers, I know right off the bat that any Guid type should be hidden. It’s not always the case, so I’d like to support the attribute if needed.

Editors.IfPropertyIs<Guid>().Attr("type", "hidden");
Editors.IfPropertyIs<Guid?>().Attr("type", "hidden");
Editors.IfPropertyHasAttribute<HiddenInputAttribute>().Attr("type", "hidden");


Number

Number inputs are a bit complicated. I actually tend to avoid them, as I find they’re not really that usable. However, I do want to provide some hints to the user as well as some rudimentary client-side validation with the “pattern” attribute.

Editors.IfPropertyIs<decimal?>().ModifyWith(m =>
    m.CurrentTag
    .Data("pattern", "9{1,9}.99")
    .Data("placeholder", "0.00"));

I’d do similar for other numeric types (integer/floating point).

Password

We’ll use the same strategy as our hidden input – key off the name if we can, otherwise check for an attribute.

Editors.If(er => er.Accessor.Name.Contains("Password"))
    .Attr("type", "password");
Editors.If(er =>
{
    var attr = er.Accessor.GetAttribute<DataTypeAttribute>();
    return attr != null && attr.DataType == DataType.Password;
}).Attr("type", "password");

We had to get a little fancy with our attribute check, but nothing too crazy.

Radio

Radio buttons represent a selection of a group of items. In my code, this is represented with an enum. Since radio buttons are a bit more complicated than just an input tag, we’ll need to build out the list of elements manually. We can either build up our select element from scratch, or modify the defaults. I’m going to go the modification route, but because it’s a little more complicated, I’ll use a dedicated class instead:

Editors.Modifier<EnumDropDownModifier>();

// Our modifier
public class EnumDropDownModifier : IElementModifier
{
    public bool Matches(ElementRequest token)
    {
        return token.Accessor.PropertyType.IsEnum;
    }

    public void Modify(ElementRequest request)
    {
        var enumType = request.Accessor.PropertyType;

        request.CurrentTag.RemoveAttr("type");
        request.CurrentTag.TagName("select");
        request.CurrentTag.Append(new HtmlTag("option"));
        foreach (var value in Enum.GetValues(enumType))
        {
            var optionTag = new HtmlTag("option")
                .Value(value.ToString())
                .Text(Enum.GetName(enumType, value));
            request.CurrentTag.Append(
                optionTag);
        }
    }
}

Element modifiers and builders follow the chain of responsibility pattern, where any modifier/builder that matches a request will be called. We only want enums, so our Matches method looks at the accessor property type. Again, this is where our conventions show their power over MVC templates. In MVC templates, you can’t modify the matching algorithm, but in our example, we just need to supply the matching logic.

Next, we use the Modify method to examine the incoming element request and make changes to it. We replace the tag name with “select”, remove the “type” attribute, but leave the other attributes alone. We append a child option element, then loop through all of the enum values to build out name/value options from our enum’s metadata.

Why use this over EnumDropDownListFor? Pretty easy – it gets all of our other conventions, like the Bootstrap CSS classes. In a system with dozens or more enumerations shown, that’s not something I want to repeat all over the place.

Telephone

We’ll treat the telephone just like our password element – check for a property name, and fall back to an attribute.

Editors.If(er => er.Accessor.Name.Contains("Phone"))
    .Attr("type", "tel");
Editors.If(er =>
{
    var attr = er.Accessor.GetAttribute<DataTypeAttribute>();
    return attr != null && attr.DataType == DataType.PhoneNumber;
}).Attr("type", "tel");

If we want to enforce a specific pattern, we’d use the appropriate data-pattern attribute.

Text

This is the default, so nothing to do here!

Url

Just like our password, we’ll look at the property name, then an attribute:

Editors.If(er => er.Accessor.Name.Contains("Url"))
    .Attr("type", "url");
Editors.If(er =>
{
    var attr = er.Accessor.GetAttribute<DataTypeAttribute>();
    return attr != null && attr.DataType == DataType.Url;
}).Attr("type", "url");

If we get tired of typing that attribute matching logic out, we can create an extension method:

public static class ElementCategoryExpressionExtensions
{
    public static ElementActionExpression HasAttributeValue<TAttribute>(
        this ElementCategoryExpression expression, Func<TAttribute, bool> matches)
        where TAttribute : Attribute
    {
        return expression.If(er =>
        {
            var attr = er.Accessor.GetAttribute<TAttribute>();
            return attr != null && matches(attr);
        });
    }
}

And our condition becomes a bit easier to read:

Editors.If(er => er.Accessor.Name.Contains("Url"))
    .Attr("type", "url");
Editors
    .HasAttributeValue<DataTypeAttribute>(attr => attr.DataType == DataType.Url)
    .Attr("type", "url");


Wrapping up

We knocked out most of the HTML5 input element types, leaving out ones that didn’t make too much sense. We can still create conventions for those missing elements, likely using property names and/or attributes to determine the right convention to use. Quite a bit more powerful than the MVC templates!

Next up, we’ll look at more complex element building example where we might need to hit the database to get a list of values for a drop down.

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

Categories: Blogs

Conventional HTML in ASP.NET MVC: Baseline behavior

Thu, 07/17/2014 - 16:11

Other posts in this series:

Now that we’ve got the pieces in place for building input/display/label conventions, it’s time to circle back and figure out what exactly we want our default behaviors to be for each of these components. Because it’s so easy to modify the tags generated programmatically, we can establish some pretty decent site-wide behavior for our system.

First, in order to establish a baseline, we need to examine what our current implicit standards are. Right now I’m solely focused on only the input/label/display elements, and not how these elements are typically composed together (label + input etc.). Looking at several of our inputs, we see a prevalent pattern. All of the input elements (ALL of them) have a CSS class appended to them for Bootstrap, “form-control”. Appending this in our normal method of the MVC templated helpers is actually quite difficult and esoteric. For us, it’s a snap.

First, let’s create our own HtmlConventions class that inherits from the default:

public class OverrideHtmlConventions 
    : DefaultHtmlConventions {
}

We’ll then redirect our container configuration to use this convention library instead:

public class FubuRegistry : Registry
{
    public FubuRegistry()
    {
        var htmlConventionLibrary 
             = new HtmlConventionLibrary();
        var conventions
             = new OverrideHtmlConventions();
        htmlConventionLibrary.Import(.Library);
        For<HtmlConventionLibrary>().Use(htmlConventionLibrary);

The OverrideHtmlConventions class is where we’ll apply our own conventions on top of the existing ones. The base conventions class lets us apply conventions to several classes of items:

  • Displays
  • Editors
  • Labels

And a couple of things I won’t cover as I’ve never used them:

  • Forms
  • Templates

There’s no real difference between the Displays/Editors/Templates conventions – it’s just a way to segregate strategies and conventions for building different kinds of HTML elements.

Conventions work by pairing a filter and a behavior. The filter is “whom to apply” and the behavior is “what to do”. You have many different levels of applying filters:

  • Always (global)
  • Attribute existence (w/ filtering on value)
  • Property metadata

The last one is interesting – you have the entire member metadata to work with. You can look at the property name, the property type and so on.

From there, your behaviors can be as simple or complex as you need. You can:

  • Add/remove CSS classes
  • Add/remove HTML attributes
  • Add/remove data attributes
  • Replace the entire HTML tag with a new, ground-up version
  • Modify the HTML tag and its children

You have a lot of information to work with, the original value, new value, containing model and more. It’s pretty crazy, and a lot easier to work with than the MVC metadata (which goes through this ModelMetadata abstraction).

I want to set up our “Always” conventions first, which means really only adding CSS classes. The input elements are easy:

Editors.Always.AddClass("form-control");

Our input elements become a bit simpler now:

@*Before*@
@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
@*After*@
@Html.Input(m => m.Email)

Our labels are a bit more interesting. Looking across the app, it appears that all labels have two CSS classes applied, one pertaining to styling a label, and one pertaining to width. At this point we need to make a judgment call. Do we standardize that all labels are a certain width? Or do we force all of our views to explicitly set this class?

Luckily, we can still adopt a site-wide convention and replace this CSS class as necessary. Personally, I’d rather standardize on how screens should look rather than each new screen becoming a point of discussion on how wide/narrow things are. Standardize, but allow deviation. Our label configuration now becomes:

Editors.Always.AddClass("form-control");
Labels.Always.AddClass("control-label");
Labels.Always.AddClass("col-md-2");

Then in our HTML, we can replace our labels with our convention-based version:

<div class="form-group">
    @Html.Label(m => m.Email)
    <div class="col-md-10">
        @Html.Input(m => m.Email)
    </div>
</div>
<div class="form-group">
    @Html.Label(m => m.Password)
    <div class="col-md-10">
        @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
    </div>
</div>
<div class="form-group">
    @Html.Label(m => m.ConfirmPassword)
    <div class="col-md-10">
        @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
    </div>
</div>

It turns out in this app so far we’re not using display elements, but we could go a similar path (surrounding the element with a span tag etc).

So what about those other methods, the “PasswordFor” and so on? In the next article, we’ll look at replacing all of the form helpers with our version, based solely on metadata that already exists on our view models.

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

Categories: Blogs

Conventional HTML in ASP.NET MVC: Adopting Fubu conventions

Fri, 07/11/2014 - 17:42

Other posts in this series:

Now that we’ve established a base for programmatically building out HTML, we can start layering on top more intelligent model-centric conventions for both displaying and editing data. Eventually, I want to get to the point of not just supporting simple conventions like “DateTime = date picker” and “bool = checkbox” but much more powerful ones. Things like “a property named ‘Comments’ should be a textarea” or “a property of an entity type should make its dropdown options the list of items from the database”. These are all things that are universal to the metadata found on those properties.

On top of that, I still want to enable customization, but at the HTML tag level. Ultimately, these builders build one or more tags, but nothing bigger than that. I don’t want to use templating for this – complex logic inside a template is difficult to do, which is why you have concepts like Ember views or Angular directives. I want to build an equivalent to those, but for MVC.

I built a rather lousy, but functional version, years ago, but missed the concept of an object model to build HTML tags. That lousy version was ported to MVC Contrib, and should not be used by anybody under any circumstances. Instead, I’ll pull in what FubuMVC already built, which turns out is built on top of the HtmlTags library.

I’m not going to use any of the other pieces of FubuMVC – just the part that conventionally builds HTML tags. First things first, we’ll need to get the Fubu MVC conventions and related packages up and running in our app.

Integrating Fubu Conventions

First, we’ll need to install the correct packages. For this, we’ll just need a couple:

  • FubuMVC.Core.UI
  • FubuMVC.StructureMap3

These two pull down a number of other packages. To make things easier on ourselves, we’ll also install the StructureMap package for integrating with MVC 5:

  • StructureMap.MVC5

Once that’s done, we have StructureMap plugged in to MVC, and the components ready for plugging FubuMVC into ASP.NET MVC. We’ll need to make sure that the correct assemblies are loaded into StructureMap for scanning:

Scan(
    scan => {
        scan.AssemblyContainingType<IFubuRequest>();
        scan.AssemblyContainingType<ITypeResolver>();
        scan.AssemblyContainingType<ITagGeneratorFactory>();
        scan.AssemblyContainingType<IFieldAccessService>();
        scan.AssemblyContainingType<StructureMapFubuRegistry>();

        scan.TheCallingAssembly();
        scan.WithDefaultConventions();
        scan.LookForRegistries();
    });

We just make sure we add the default conventions (IFoo –> Foo) for the Fubu assemblies we referenced as part of the NuGet packages. Next, we need to configure the pieces that normally are done through FubuMVC configuration, but because we’re not pulling all of Fubu, we need to do through container configuration:

public class FubuRegistry : Registry
{
    public FubuRegistry()
    {
        var htmlConventionLibrary = new HtmlConventionLibrary();
        htmlConventionLibrary.Import(new DefaultHtmlConventions().Library);
        For<HtmlConventionLibrary>().Use(htmlConventionLibrary);

        For<IValueSource>().AddInstances(c =>
        {
            c.Type<RequestPropertyValueSource>();
        });
        For<ITagRequestActivator>().AddInstances(c =>
        {
            c.Type<ElementRequestActivator>();
            c.Type<ServiceLocatorTagRequestActivator>();
        });
        For<HttpRequestBase>().Use(c => c.GetInstance<HttpRequestWrapper>());
        For<HttpContextBase>().Use(c => c.GetInstance<HttpContextWrapper>());
            
        For<HttpRequest>().Use(() => HttpContext.Current.Request);
        For<HttpContext>().Use(() => HttpContext.Current);

        For<ITypeResolverStrategy>().Use<TypeResolver.DefaultStrategy>();
        For<IElementNamingConvention>().Use<DotNotationElementNamingConvention>();
        For(typeof(ITagGenerator<>)).Use(typeof(TagGenerator<>));
        For(typeof(IElementGenerator<>)).Use(typeof(ElementGenerator<>));
    }
}

There’s a bit here. First, we create an HtmlConventionLibrary, import default conventions, and register this instance with the controller. We’re going to modify this in the future but for now we’ll use the defaults. This class tells FubuMVC how to generate HtmlTag instances based on element requests (more on that soon). Next, we register a value source, which is analogous to a ValueProvider in MVC. The ITagRequestActivator is for filling in extra details around a tag request (again, normally filled in with FubuMVC configuration).

Since FubuMVC still has pieces that bridge into ASP.NET, we need to register the HttpContext/Request classes based on HttpContext.Current. In the future ASP.NET version, this registration would go away in favor of Web API’s RequestContext.

The ITypeResolverStrategy determines how to resolve a type based on an instance. I included this because, well, something required it so I registered it. Much of this configuration was a bit of trial-and-error until pieces worked. Not a knock on Fubu, since this is what you deal with bridging two similar frameworks together. Still much cleaner than bridging validation frameworks together *shudder*.

The IElementNamingConvention we’re using tells Fubu to use the MVC-style notation for HTML element names (foo[0].FirstName). Finally, we register the open generic tag/element generators. Even though the naming convention is IFoo->Foo, StructureMap doesn’t automatically register open generics.

This is the worst, ugliest part of integrating Fubu into ASP.NET MVC. If you can get past this piece, you’re 100 yards from the marathon finish line.

Now that we have Fubu MVC configured for our application, we need to actually use it!

Supplanting the helpers

Because the EditorFor and DisplayFor are impossible to completely replace, we need to come up with our own methods. FubuMVC exposes similar functionality in InputFor/DisplayFor/LabelFor methods. We need to build HtmlHelper extensions that call into FubuMVC element generators instead:

public static class FubuAspNetTagExtensions
{
    // Similar methods for Display/Label
    public static HtmlTag Input<T>(this HtmlHelper<T> helper, 
        Expression<Func<T, object>> expression)
        where T : class
    {
        var generator = GetGenerator<T>();

        return generator.InputFor(expression, model: helper.ViewData.Model);
    }

    private static IElementGenerator<T> GetGenerator<T>() where T : class
    {
        var generator = DependencyResolver.Current.GetService<IElementGenerator<T>>();
        return generator;
    }
}

We build an extension method for HtmlHelper that accepts an expression for the model member you’re building an input for. Next, we use the dependency resolver (service location because MVC) to request an instance of an IElementGenerator based on the model type. Finally, we call the InputFor of IElementGenerator to generate an HtmlTag based our expression and model. Notice there’s no ModelState involved (yet). We’ll get to validation in the future.

Finally, we need to use these Label and Input methods in our forms. Here’s one example from the Register.cshtml view from the default MVC template:

<div class="form-group">
    @Html.Label(m => m.Email).AddClass("col-md-2 control-label")
    <div class="col-md-10">
        @Html.Input(m => m.Email).AddClass("form-control")
    </div>
</div>
<div class="form-group">
    @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
    </div>
</div>

I left the second alone to contrast our version. So far not much is different. We do get a more elegant way of modifying the HTML, instead of weird anonymous classes, we get targeted, explicit methods. But more than that, we now have a hook to add our own conventions. What kinds of conventions? That’s what we’ll go into the next few posts.

Ultimately, our goal is not to build magical, self-assembling views. That’s not possible or desirable. What we’re trying to achieve is standardization and intelligence around building model-driven input, display, and label elements. If you’re familiar with Angular directives or Ember views, that’s effectively what our conventions are doing – encapsulating, with intelligent, metadata-driven HTML elements.

Next up: applying our own conventions.

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

Categories: Blogs

Survey of two large MVC projects

Wed, 06/25/2014 - 17:17

A large-ish MVC project in which I led the architecture is hitting a milestone of 12 months in development (though released to production for some months now). It’s a similar project to the one where AutoMapper came from, but this time targeting a more focused domain, and subject of the How We Do MVC post.

Much of the patterns discussed come from a certain context, especially on optimizations I look at for accelerating delivery that don’t necessarily apply to other systems. Some comparison stats between these two projects:

Project A

  • ~6 years of continuous development at various pace
  • Over 100 deployments to customers statewide
  • 352 Controllers
  • 1079 Actions
  • 3 actions/controller

Project B

  • 12 months of continuous development at continuous pace
  • At least one deployment to a customer, a few more planned this year, then dozens the next
  • 71 Controllers
  • 534 Actions
  • 7.5 actions/controller

So while B only has 20% of the controllers of A, it has half the actions. This is for a couple of reasons:

  • 6 years ago AJAX was difficult for accessibility. Not the case any more, so AJAX plays a much bigger role
  • Task-based UIs mean a lot more contextual actions take place on one screen, depending a large number of factors

All these “put XYZ” on a diet talks, preferring slices over layers, and in general wanting new features to only add classes and files and not modify them is because of the scope of projects I generally deal with. I have to come up with tools and techniques to address design challenges of this scope, so tools like AutoMapper, the mediator pattern, feature folders, HTML conventions, slices over layers, no convoluted project structure and so on are critical to allow this sort of project to continue at a pace without slowing down under its own weight.

In this project, we had no repositories. No layered project structure. No abstractions over dependencies. No vegetable-based architectures. The last 12 months had roughly 250 working days, which averages out to a new controller every 3.5 days and a little over 2 new controller actions every single day. That sort of pace can only come from a laser focus on highly cohesive code, where each new feature only added requisite classes for feature where pieces differed, and allowing conventions to fill in mundane details that we intended to be consistent site-wide.

I’ve already covered our designs in our controllers, next, I’ll pick up the conventional HTML post that allowed us to create a highly streamlined process for building out our views (and how we extended this concept to client-side templates).

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

Categories: Blogs

Missing EF Feature Workarounds: Filters

Thu, 05/29/2014 - 18:42

Filters are one of those ORM features that when you need it, you REALLY need it. NHibernate has had this feature for quite a long time, but it still doesn’t exist in EF. What are filters? In NHibernate, a filter is

a global, named, parameterized filter that may be enabled or disabled for a particular NHibernate session

The scenarios for this feature are pretty extensive:

  • Soft deletes
  • Multi-tenancy (with a tenant ID column)
  • Security
  • Active/inactive records
  • Logical data partitions

Basically, any time you want to apply a predicate to a set of entities when queried, but not force the developer to “remember” to add that clause. The typical approach in EF is with extension methods or base DbContext/Repository classes, but both of these approaches are limited.

Fortunately, EF exposes an extension point to alter the DB query before it goes out the door and gets executed in the form of interceptors. There are two levels of interception:

  • DbCommand
  • DbCommandTree

With the DbCommand, you’re at the SQL level, not where I want to be. Instead, we can work with an expression tree and alter it accordingly. And because this was a bit extensive, I wound up creating an OSS extension for EF to accomplish filters:

https://github.com/jbogard/EntityFramework.Filters

https://www.nuget.org/packages/EntityFramework.Filters/

I used the NHibernate design for EF, in that you define your filters with the entity metadata, and the parameters of the filter on an instance of your DbContext:

public class FooContext {
    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Entity<Listing>()
            .Filter("ActiveListings", c => c.Condition<ListingStatus>(
                listing => listing.Status == ListingStatus.Active));
        
        // Create parameterized filter for all entities that match type
        // In this case, DB is multi-tenant, with AgencyId as tenant column on _all_ tables
        modelBuilder.Conventions.Add(
            FilterConvention.Create<IAgencyEntity, int>("Agency", (e, agencyId) => e.AgencyId == agencyId);
    }
}

// usage, filters disabled by default
dbContext.EnableFilter("ActiveListings");
dbContext.EnableFilter("Agency")
    .SetParameter("agencyId", _userContext.CurrentUser.AgencyId);

// can disable filters
dbContext.DisableFilter("ActiveListings");

There are some limitations and the queries aren’t as powerful as what you can do in NHibernate, but the basic scenarios are there. Because filter parameter values are scoped against an instance of a DbContext, you can effectively partition the filter values based on specific scenarios/contexts. Behind the covers, I translate the LINQ expression passed in via filter configuration to a DbExpression, substitute the contextual parameter values appropriately, and append the result as an additional filter to your query.

For example, different users in a multi-tenant environment will have their tenant filter applied based on their specific tenant:

// In our authentication filter in MVC
var user = dbContext.Users
    .Where(u => u.UserName == form.UserName)
    .FirstOrDefault();

dbContext.EnableFilter("Tenant")
    .SetParameter("tenantId", user.TenantId);

// In our controller, only retrieves orders for this tenant
var orders = dbContext.Orders.ToList();

The GitHub readme has more details, and the code can at least provide an inspiration for those that want to do something a bit more dynamic than what was shown at Tech Ed.

It was an interesting exercise implementing pretty complicated extension to EF, one that was greatly helped by having access to the actual source code, but hindered when nearly all the interesting work happening in EF is marked “internal”. In order to facilitate easy development, I wound up forking EF, replacing all “internal” modifiers with “public”, getting my solution working, then reverting back to the original EF version. Strong-naming may be a pain to OSS development, but highly conservative use of “public” is far more limiting in my experience.

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

Categories: Blogs