5

I'm developing some code generator for generating models, controllers and views based on databases tables so I could make a Asp.Net MVC3 website. I can generate models and controllers with CodeDOM now but for generating views I need something to make the templates , like generating a .cshtml from a .cs , I thought T4 would be good idea but some of my colleagues insist on not using T4, is there any other ways? thanks

ePezhman
  • 4,010
  • 7
  • 44
  • 80
  • What is wrong with t4 according to your colleague? – Wiktor Zychla Oct 13 '12 at 21:16
  • 3
    Not sure why your colleagues don't want to use T4. It's a very powerful system, and it's free. It comes with Visual Studio, so there are no extra licensing costs. That's a huge incentive to use it. – Erik Funkenbusch Oct 14 '12 at 04:03
  • I don't know exactly , they say it's kinda messy and hard to make some clean code. – ePezhman Oct 15 '12 at 10:33
  • 1
    Its not messy at all.. its C# code wrapping whatever code you want to generate :) ill post example of a template i use in my answer. – Tony Oct 16 '12 at 14:14
  • @Tony - I can see why they might think it's messy. In T4 you have code sections and output sections. In Razor, you have code sections and output sections. So when you use T4 to write your Razor, you are using code to output code to output HTML, which could potentially turn into a tangled knot. I'm not saying that it *can't* be done, or that it isn't the best way - just that I can see where they could be coming from. – Bobson Oct 19 '12 at 00:37
  • @Bobson, I can see what you are saying as well. But wouldn't any code generation tool lead to the same path? Generating some code, that is used to generate some code that generates html :) He could however use the T4 to help him generate HTML helpers that would make generating the views easier. He could also make the views generic enough that he can pass the types in and have it generate from the model. Plenty of way to skin the cat.. I could be bias but after this extreme project I just finished using T4 to generate so crazy stuff.. I can't see why you would want to use anything else :) – Tony Oct 19 '12 at 13:25

5 Answers5

6

I am not sure why they would be against using T4 as a lot of the code libraries out there including Entity Framework use them. It sounds like you are doing something I just finished doing. I liked using Pre-Processed T4 templates so I am able to feed data into them from C# code and generate the files that way. This allows you to have multiple files output and basically parameters to pass data in with.

The way I use it is.. I made a class that was used to gather all the information about the databases.. which tables to include or exclude.. and then information about each column like pk or identity nullable and such. I plugged my preprocessed t4 templates in with that information was was able to generate all the SQL, views, models, controller info.. and whenever the database changed.. i just run my console app and bam its all regenerated.

Preprocessed: http://odetocode.com/Blogs/scott/archive/2011/01/03/preprocessed-t4-templates.aspx

Entity Framework: http://msdn.microsoft.com/en-us/data/gg558520.aspx

MVCScaffolding: http://blog.stevensanderson.com/2011/04/06/mvcscaffolding-overriding-the-t4-templates/

T4MVC: http://mvccontrib.codeplex.com/wikipage?title=T4MVC

Again i know this doesn't help answer your question but T4 is AMAZING and I would be interested to hear the arguement on why not to use T4.. its even built in!

btw here gets some intellisense!: http://t4-editor.tangible-engineering.com/T4-Editor-Visual-T4-Editing.html

If yo have any questions please feel free to hit me up I love T4 and i'd be willing to answer any questions I can.

Here is an example of a template I use to generate my POCO models.. a lot has been extracted thanks to the pre-processed abilities of using my normal c# methods to pass data in. This template creates 55 models for me based off of the tables in a database.

My "SchemeCollector" uses a DatabaseInfo, TableInfo, and ColumnInfo class that I created to hold all the schema I need. Then I have 9 other t4 templates that also use the SchemaCollector class to populate the data.

Here is the extension I use to pass the data into the template for generation. I have this all setup to use XML files for configuration also but it is unnecessary I just wanted it to be really reusable.

public partial class PocoGenerator
    {
        public string Namespace { get; set; }
        public string Inherit { get; set; }
        public DatabaseInfo Schema { get; set; }
        public bool Contract { get; set; }
        public string SavePath { get; set; }
    }

Here is the method I use to call and populate the template and save it.

static void GeneratePoco(Config config)
        {
            var template = config.Poco;
            template.Schema = config.DatabaseInfo;

            File.WriteAllText(template.SavePath, template.TransformText());

            Console.WriteLine("      - POCOs generated for " + config.DatabaseInfo.DatabaseName + " complete");
        }

Here is the template

<#@ template  debug="true" hostSpecific="true" #>
<#@ output extension=".cs" #>
<#@ Assembly Name="System.Core.dll" #>
<#@ Assembly Name="System.Windows.Forms.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #> 
<#@ assembly name="System.Xml.dll" #>
<#@ assembly name="System.Data.dll" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="CodeGenerator.Utilities" #>

using System;
using System.Runtime.Serialization;

namespace My.Models
{   <#  
        List<TableInfo> tables = Schema.Tables; 
    #>

    //#########################################################################################################
    //   This file has been generated from the tables contained in the <#= Schema.DatabaseName #> database.
    //   Changes to this file will be overwritten when the file is regenerated. Generated: <#= DateTime.Now #>
    //#########################################################################################################
    <#
    foreach (TableInfo table in tables)
    {
    #>

    [DataContract]
    public class <#= table.Name #> : IConfigTable
    {

        <#
        PushIndent("        "); 
            foreach (ColumnInfo col in table.Columns)
            {
                if(col.IsKey || col.IsIdentity)
                    WriteLine("[Key]");

                WriteLine("[DataMember]");
                if(col.IsNullable && col.Type != "string")
                    WriteLine("public " + col.Type + "? " + col.Name+ " { get; set; }");
                else
                    WriteLine("public " + col.Type + " " + col.Name+ " { get; set; }");
            }PopIndent();#>     
    }
    <# } #>
}
Tony
  • 3,269
  • 1
  • 27
  • 48
1

Your answer is here: https://stackoverflow.com/a/2457206/538387

Which has a link to ASP.NET MVC and virtual views

Community
  • 1
  • 1
Tohid
  • 6,175
  • 7
  • 51
  • 80
0

We used code smith extensively and also wrote a plugin. With t4 though ou could simply generate the classes and then remove the template - why the opposition there to T4?

Adam Tuliper
  • 29,982
  • 4
  • 53
  • 71
  • @wiktor zychla, it addresses the question asked 'are there other ways' to which I answered – Adam Tuliper Oct 13 '12 at 22:12
  • thanks, I checked that out, for this step I'm more looking for something open source and free – ePezhman Oct 15 '12 at 10:29
  • ePez. T4 is built into VS I am really interested in finding out why it is unacceptable? I know the questions is what other ways.. but honestly it is so powerful why would you need any other way? – Tony Oct 18 '12 at 17:46
  • @Tony one would make an argument theres no UI available for parameters which is one reason we created a plugin to have a more interactive wizard, but some scenarios are clearly just fine for T4. – Adam Tuliper Oct 19 '12 at 14:49
  • @Adam, That could be an argument but then again I guess use case would matter. As .Net developers we generally do not have an UI to pass our parameters with. Using pre-compiled T4 templates you would pass the parameters to it just like any other method. In my example GeneratePoco is the partial class related to the template. You create what parameters you want the template to use and pass them in. Then you take the type and template.TransformText() to apply the parameters. So technically, if you want a UI you could create one. – Tony Oct 19 '12 at 19:02
0

Certainly, I use Razor for all my code generation (and email generation, etc.) by using the nice extension RazorGenerator. It allows you to specify this extension as a "custom tool" and generates a resultant C# class off of your .cshtml input that you can invoke (and pass in a @model) to transform text into whatever output you like. (somewhat ironically in your case, it would be razor => razor conversions)

Kirk Woll
  • 76,112
  • 22
  • 180
  • 195
  • I run this razorGenerator now, as you said it generate from .cshtml, I need to generate to .cshtml I don't need precompiled views. – ePezhman Oct 15 '12 at 10:32
  • @ePezhman, what is it about my answer that makes you think you can't use this technique to generate `.cshtml` files? (that's what I meant by "razor => razor conversions") – Kirk Woll Oct 15 '12 at 13:44
  • I guess the razorGenerator is for making precompiled razor views, I worked a little with that and I couldn't see any options to get a .cshtml output. – ePezhman Oct 15 '12 at 14:59
0

We have similar task, we are crating dynamic web forms that are based on input json file with form definition. Editor specify different controls that should be presented on a form (controls contain different properties, actions, validators). Below i will try to describe basic procedure of a our logic:

  1. Deserilize and validate json file.
  2. Prepare data that will be passed to the T4 template.
  3. Generate MVC models and controller from the data (step 2).
  4. Generate additional classes (e.g. some helpers, complex types from a model).
  5. Add to assembly embeded resources such a dataSources etc, images whatever.
  6. Compile all stuff above.
  7. Drop dll in models folder.
  8. Restart site.

All properties in the model has their [UIHint] attributes with names of a partial views. We have around 10 partial views that knows how to represent each property. To support this logic we extend ViewEngine and ModelMetadata provider.

ViewEngine looks for views in additional folder. ModelMetada provider adds to "AdditionalValues" custom properties.

Our view for a model have one row

@Html.EditorForModel()

We had overrided Object.cshtml to handle 'deep binding'. The most difficult parts was with a collections where collection items were of a complex type.

user854301
  • 5,383
  • 3
  • 28
  • 37