Viewing entries tagged
ASP.NET Dynamic Data

3 Comments

Dynamic Data - Working with ASP.NET Membership provider and hiding the aspnet tables using T4 Templates

There are two ways to work when using ASP.NET Dynamic Data:

  1. Automatically Scaffold everything
  2. Scaffold only those tables you specify

Scaffolding manually is alright but you need to remember to add the ScaffoldTableAttribute to the new tables you want managed by ASP.NET Dynamic Data

I prefer to let it automatically scaffold all tables so as I’m developing and changing the database schema I automatically get the CRUD pages. I then choose which ones to exclude.

Note: You can scaffold all tables by setting the ScaffoldAllTables property to true in your Global.asax.cs

model.RegisterContext(typeof(TestDataContext), new ContextConfiguration() { ScaffoldAllTables = true });

This is great, until you start using the ASP.NET Membership and Role providers. When you use these (integrated into the one database) it adds a lot of aspnet_* tables to your database so when you regenerate your LINQ to Entities/SQL file.

ASPNET-MembershipTables.png DynamicData-MembershipTables.png

You can avoid these issues if you make ASP.NET generate these tables into a separate database but if you like everything in one database then there is a solution for you. T4 Templates - built right into Visual Studio. We can use these templates to automatically exclude the aspnet tables.

  1. Download Damien Guard’s LINQ to SQL templates. You will only need the L2ST4.ttinclude file.

     

  2. Create a MetaData folder in your solution
  3. Add new new file and call it MetaData.tt (you might be prompted with a warning - click OK)
  4. Paste the following code in:
    		<#@ template language="C#v3.5" hostspecific="True"#>
    <#@ include file="../L2ST4.ttinclude"#>
    <#@ output extension=".generated.cs"#>
    <# // Template by Eric Phan http://ericphan.info inspired by Damien Guard http://damieng.com
    var data = new Data(Host.TemplateFile.Replace("MetaData.tt","../NAMEOFYOURDBML.dbml")); 
    var code = new CSharpCodeLanguage();
    data.Serialization = SerializationMode.DataContractSP1;
    #>
    #pragma warning disable 1591
    //------------------------------------------------------------------------------
    // 
    // This code was generated by LINQ to SQL template for T4 C# v0.79
    // Generated at <#=DateTime.Now#>
    //
    // Changes to this file may cause incorrect behavior and will be lost if
    // the code is regenerated.
    //
    //------------------------------------------------------------------------------ using System; using System.ComponentModel; using System.Data.Linq; using System.Data.Linq.Mapping; using System.ComponentModel.DataAnnotations; using <#=data.EntityNamespace#>.MetaData; namespace <#=data.EntityNamespace#>.MetaData { <# foreach(Table table in data.Tables) { foreach(TableClass class1 in table.Classes) { if (class1.Name.StartsWith("Aspnet_")) {#> [ScaffoldTable(false)]<#}#> public partial class <#=class1.Name#>MetaData {<# if (class1.Columns.Count > 0) foreach(Column column in class1.Columns) if (column.IsPrimaryKey) { #> [ScaffoldColumn(false)] public object <#=column.Member#> { get; set; } <#}#> } <#}}#>} namespace <#=data.EntityNamespace#> { <# foreach(Table table in data.Tables) { foreach(TableClass class1 in table.Classes) { #> [MetadataType(typeof(<#=class1.Name#>MetaData))] public partial class <#=class1.Name#> { } <#}}#> } #pragma warning restore 1591
  5. RIght click on MetaData.tt and click Run Custom Tool
  6. Look at the MetaData.generated.cs file

Note: MetaData.tt will create all partial classes based on your DBML file, create the associated metadata classes and associate them to the class. It will also add the ScaffoldTable(false) attribute to any Aspnet tables and automatically unscaffold any primary key columns (workaround for GUID issue)

Resources

3 Comments

Comment

Dynamic Data - Validation

ASP.NET Dynamic Data is fantastic in that it automatically picks up simple validation straight from your DBML/EF model.

It will pick up things like required fields, data types and maximum lengths. You can also manually assign validation rules to your classes using metadata and validation attributes.

The following is a list of available validators from the System.ComponentModel.DataAnnotations namespace.

You use these by attribute by creating a metadata class and associating it with your domain class using the MetadataType attribute

[MetadataType(typeof(CustomerMetadata))]
public partial class Customer { }

public class CustomerMetadata
{
	[Required(ErrorMessage = "First Name is a required field")]
	[StringLength(30, ErrorMessage="The customer's first name cannot be more than 30 characters")]
	public object FirstName { get; set; }

	[RegularExpression(@"\b[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b")]
	public object EmailAddress { get; set; }

	[Range(18,150, ErrorMessage = "Customer must be 18 to 150 years old")]
	public object Age { get; set; }
}

Note: Make sure the partial class is in the same namespace as your DBML/EF classes.

Now you get extra validation with a few lines of code.

Comment

2 Comments

ASP.NET Dynamic Data - GUIDs

Dynamic Data by default doesn’t play well with GUID primary keys, or more correctly LINQ to SQL doesn’t auto generate the GUIDs for you by default. You will get validation errors when you try to insert

Note: the Entity Framework also suffers from this problem

You have two options here:

Option 1 - Set the Auto Generate Property to True

  1. In the DBML Designer, select the GUID primary key and select Properties
  2. Set the Auto Generated Value property to True
  3. Now the UserID field is hidden in the insert page and we are able to successfully insert

The problem with this method is that every time the DBML file gets regenerated you lose this change and you get the validation error again. For a more permanent solution you can try option 2

Option 2 - Turn Scaffolding off through metadata

  1. Create a metadata class and add the ScaffoldColumn(false) attribute to the UserID field
	using System.ComponentModel.DataAnnotations;

	[MetadataType(typeof(UserMetadata)]
	public partial class User { }

	public partial class UserMetadata
	{
		[ScaffoldColumn(false)]
		public object UserID { get; set; }
	}

This gives you a more permanent solution that can survive regenerating your DBML

2 Comments