Some Considerations For MVC 6 Client Attributes

One of the new features coming is the addition of Tag Helpers, which are server-side attributes that get interpreted and translated into a client-side attributes. This transforms the previous approach we used to use of the following:

@Html.ActionLink("Text", "Action", "Controller")
@* OR *@
<a href="@Url.Action("Action", "Controller")">Text</a>

Both of the above examples translate to the same result; Html.ActionLink builds a link with a single HREF attribute. One of the changes available with tag helpers is to instead use new “asp” prefixed attributes to perform the rendering:

<a asp-controller="Controller" asp-action="Action">Text</a>

These attributes get translated to a href client-side attribute with the appropriately generated URL. There are a variety of tags available that support server-side attributes, outside of the hyperlink. For instance, the form and label tags also support attributes, as well as others that you can find more at the following resources:

There is lots of good content out there on the subject already. I wanted to discuss in this post the merits of tag helpers, and discuss some of the pros and cons. Whatever is discussed with tag helpers, it’s important to remember that you can always utilize the old way of developing the user interface. To my knowledge, that isn’t going away.

It is important to remember that tag helpers are server-side; they still run server-side code, and so you cannot use asp attributes at client time. The client-side interpreters do not know of these attributes, but the server does as in this post. So if you like to use jQuery or Kendo UI templating, tag helpers won’t really give you much, as you have to render the link anyway. Now, there are server-side tricks to rendering client content that can be utilized, which I have written about in the past on this blog, and so there are ways to leverage that depending on what you are doing.

You also have to be careful which attributes you use where, as certain attributes are supported for certain tags. I haven’t found a comprehensive list yet, other than the Mikesdotnetting post. So be careful as you use new attributes to account for that. Also, some properties define expressions to the field in the model that may contain additional information. For instance, the label may support a field to grab the display information. In this case, the attribute defines the name of the field to display information for, which corresponds to the property in the model. It will be interesting to see how Tag Helpers support deep nested models, and whether we need to render names like Customers[0].FirstName when working with lists. This is one area where the old tags make it a little more clear.

These are some preliminary ideas to think about; I’m sure I’ll be amending this post as I think of other considerations after publishing this post 🙂

Advertisements

Entity Framework Table Tricks

I’ve seen out on the web quite a few questions about how to do this or that with Entity Framework, so I’d thought I’d write up a solution to various ways to work with tables and to customize entities.

Sets

Suppose we have a context with a Customers table; by default, the Entity Framework code generator generates code that allows the consumer to do the following.

var ctx = new EFContext();
ctx.Customers.Where(i => ..);

The Customers property is a DBSet object that is responsible for “table management”, which is not quite right but a good quick way to understand it. The DBSet is the primary mechanism for generating queries against the table and adding new objects to the table. Entity Framework code generators create wrappers around this object, but also expose the following methods in two forms:

public System.Data.Entity.DbSet Set(Type type);
public System.Data.Entity.DbSet Set();

Referring to a table generically using the set method comes in handy when you want to simplify your data access code. To explain what I mean, let’s look at a small sample. We may want to use the repository pattern like this:

public interface IRepository
 where T: class
{

    IEnumerable GetAll();

}

public class CustomerRepository : IRepository
{
   public IEnumerable GetAll()
   {
      var ctx = new EFContext();
      return ctx.Customers.ToList();
   }
}

Note how we write the code in each and every repository; we have 1 now, but as the system grows, each repository has to write this same code over and over again. Sure, we can generate it automatically, but we can also do this:

public abstract class BaseRepository : IRepository
{
   public IEnumerable GetAll()
   {
      var ctx = new EFContext();
      return ctx.Set().ToList();
   }
}

public class CustomerRepository : BaseRepository
{

}

Notice the set method usage and how this one common method prevents us from having to write common code. Now we have one method shared across all repositories. We could also use the other override like so:

ctx.Set(typeof(Customer));

Although, it’s far less flexible than the generic form. A lot of the common options are not available out-of-the-box. One important use you can use it to add objects to the database, however.

var customer = new Customer { .. };
ctx.Set(typeof(Customer)).Add(customer);
ctx.Set().Add(customer);

ctx.SaveChanges();

SaveChanges then commits any changed made, raising errors for any validations or update exceptions.

Using Interfaces

Using interfaces can add in some nice flexibility. Suppose we have an interface like this:

public interface IAuditEntity
{
   public DateTime Entered { get; set; }

   public DateTime? Updated { get; set; }
}

Supposing that all of your entities implement this interface, you can simplify your repositories by creating common code:

public abstract class BaseRepository
{

   public IEnumerable GetUpdatedSince(DateTime check)
      where T: IAuditEntity
   {
      var ctx = new EFContext();
      return ctx.Set().Where(i => i.Updated != null && i.Updated.Value > check);
   }

}

While the example above is not the most useful, it illustrates what can be done to create common routines in entity framework. Since Updated matches the name of a field in the table being queried, Entity Framework resolves this correctly; if the name doesn’t match, an exception will be raised saying the property defined in the expression doesn’t exist in the table.

Functions

What floored me though is through a method, Entity Framework can bridge the gap and provide common code. For instance, suppose we had entities like this:

public class Customer
{
   public string Country { get; set; }
}

public class Employee
{
  public string PrimaryCountry { get; set; }
}

We couldn’t create an interface with the name Country, because Employee doesn’t have a matching property. We could change the name, but for the sake of the example, let’s keep them different. Since property name mismatches cause errors, we can surprisingly use functions. An architect had shown me this and I was floored, simply because properties don’t work. But by doing:

public interface ICountry
{
   public string CountryExpression();
}

public class Customer : ICountry
{
   public string Country { get; set; }

   public string CountryExpression()
   {
      return this.Country;
   }
}

public class Employee
{
  public string PrimaryCountry { get; set; }


   public string CountryExpression()
   {
      return this.PrimaryCountry;
   }
}

And then doing the following in the query will work:

public IEnumerable GetByCountry(string country)
 where T: ICountry
{
  var ctx = new EFContext();
  return ctx.Set().Where(i => i.CountryExpression() == country);
}

An architect showed me this trick, and I was floored that it worked since properties don’t. Hopefully this post illustrated some tricks to using entity framework and reduce the overall coding needed.