Data Driven Custom View Engine in ASP.NET MVC

Posted by: Sumit Maitra , on 10/2/2013, in Category DNC Magazine
Views: 34607
Abstract: Build an ASP.NET MVC custom view engine that loads views defined in a SQL Server database

The ASP.NET MVC framework, as we know, is highly pluggable, allowing you to easily swap out pieces of the framework with custom implementation. One such piece in the framework is the View Engine. Out of the box, ASP.NET MVC comes with two view engines: the Razor View Engine and the Web Forms View Engine. Usually these default engines are enough to fulfill most of your view requirements. Both of them support decent server side template options for dynamically generating fields. However there are some scenarios that you may end up having, where the flexibility of server side template is not enough. Scenarios could be like CMS systems that actually allow you to create UI or systems that generate dynamic data entry forms where the form definition is defined by the system itself.

Of course you could also build a custom view engine just because you don’t like the verbosity of either of the two default engines!

Today we will see how we can build a web app that needs to save data form definitions in a database and then generate the views at runtime for data entry. But before we do that, let’s see what constitutes a view engine in ASP.NET MVC and how we can go about building one.

This article is published from the DotNetCurry .NET Magazine – A Free High Quality Digital Magazine for .NET professionals published once every two months. Subscribe to this eMagazine for Free and get access to hundreds of free tutorials from experts

 

Theory behind a Custom View Engine

A Custom View Engine in ASP.NET MVC plugs into the MVC pipeline towards the end of the request cycle. If you refer to Steve Sanderson’s excellent MVC Pipeline Poster, you will notice that once the Controller processes the Action, depending on whether the Return Value is ViewResult or not, the View Engine is invoked.

The View Engine returns a View Instance that implements the IView interface.

So we could have a Custom View Engine that returns a Razor view, but if you are doing that, you could probably do with HTML Helpers and don’t need a Custom View Engine. So if you are implementing a View Engine, you ideally implement an IView as well. So the final picture of this last leg of a Request’s journey is as follows:asp-mvc-view-engine-pipeline

The Incoming HTTP Request passes through various stages in the Request Pipeline before finally hitting the check for ViewEngine. If a Custom View engine is available, it runs through the view engine and if the custom view engine can render the view, it renders the appropriate View. If not, it passes the request to the next view engine available. With the picture of the Custom View Engine vis-à-vis the Request pipeline clear, let’s go ahead and build a view engine and a custom IView implementation.

Getting Started with a Custom View Engine

To get started with our View Engine, we’ll start off with a standard ASP.NET MVC 4 Project using the Internet Template. I am starting off with .NET Framework 4.5. You can select either 4.0 or 4.5. Only the usage of AntiXss Encoder will vary, as we will see later.

Implementing the IViewEngine interface

Step 1: To start off with the View Engine, we’ll add a new folder, I call it ‘Core’ but feel free to name it as you deem fit.

Step 2: Next we add a class called DbDrivenViewEngine and implement the IViewEngine interface in it.

The IViewEngine has the following methods that need to be implemented:

public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
{

}
public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{

}

public void ReleaseView(ControllerContext controllerContext, IView view)
{

}

The FindPartialView method is called when the Controller is looking to return a Partial View with the given Name. The FindView method is called when Controller is looking for a View with a given Name.  ReleaseView method is provided to release any resources that the ViewEngine might be holding on to.

Step 3: Given the ControllerContext, the viewName, the masterName and the useCache parameter, the FindView (or FindPartialView) method has to determine if it should go forth and try to render the view or pass the opportunity to other view engines in queue!

If it chooses to render the view, it will create an instance of ViewEngineResult and pass it two parameters, the IView implementation and the IViewEngine implementation. If it chooses to pass on the opportunity to the remaining view engines, it will create an Instance of the ViewEngineResult with an array of strings, specifying the locations where it failed to find the required view.

The barebones implementation for this is as follows:

public ViewEngineResult FindView(
ControllerContext controllerContext,
string viewName,
string masterName,
bool useCache)
{
if (viewName.Contains("Dynamic"))
{
  return new ViewEngineResult(new DbDrivenView(), this);
}
else
{
  return new ViewEngineResult(
   new string[]
    { "No Suitable view found for 'DbDataViewEngine', please ensure View Name contains
       'Dynamic'" });
}
}

Here we see there is a minimal check to see if the viewName contains the word ‘Dynamic’ and if it does, it tries to render it by using a new instance of DbDrivenView(). This is a class we will create in the next step so take it for its face value at the moment.

If the View Name does not contain the word ‘Dynamic’, we send back an array of string with one message as of now indicating that we didn’t find a view and the probable solution. This message is used ONLY when ASP.NET MVC falls through all the view engines and is unable to render using any one of them.

Now let’s implement the IView.

Implementing the IView interface

The DbDrivenView class that we passed into the ViewEngine Result is an implementation of the IView interface. The IView interface just has the Render method. The simplest implementation of the Render method is shown below.

public class DbDrivenView : IView
{
public void Render(ViewContext viewContext, TextWriter writer)
{
  writer.Write("Hello World");
}
}

All it does is write ‘Hello World’ to the TextWriter. We save this also under the Core folder.

Running the Rudimentary Custom View Engine

Now that we’ve got the ViewEngine and the View in place, we can technically ‘use’ it in an MVC 4 application.

Step 1: Registering the ViewEngine. To register our ViewEngine, we use the following code in our Application_Start event in the Global.asax file.

ViewEngines.Engines.Insert(0, new DbDrivenViewEngine());

As we can see, we are inserting it on the top of the already existing array of ViewEngines. This way, MVC will call our View Engine First.

Step 2: Adding an Action called ‘Dynamic’

Next we add an Action called Dynamic that returns a ViewResult. So in the HomeController we add the following code.

public ViewResult Dynamic()
{
    return View();
}

Note that the View() method is called without Parameters, this by default implies that the View Name is the same as the Action Method Name (= Dynamic). So call to this Action method will trigger our ViewEngine.

Step 4: Now if we run the application, we get our Default ASP.NET Home page. This shows that our default View Engine is in place and working fine. To trigger our ViewEngine, we navigate to the /Home/Dynamic URL. We get the following:

Hello World

Nice!!! There you go, you have a custom view engine! Go home now, we are done here!!!

Okay, I was kidding, we are far from done ;) Though most text books in ‘advanced ASP.NET series’, would have left you here, we have just gotten started. Tighten your seatbelts, its going be one heck of a ride!

Saving Custom View Definition in Database

Let us now decide how we would like to save our Dynamic View. This is where it can get as complex as you want it to be. For sake of the Demo, we’ll keep it simple.

One naming convention I am following here is, anything related to building the View and the ViewEngine I am calling it a part of ‘Core’. So the View and ViewEngine itself were a part of core. So are the Entities that help define the core Views. So the following entities, the controllers and views required to generate those entities will all be referred to as part of the Core.

The Entities

We will have a DataForm Class that will store

- Name, Description, Template and list of DataFields.

- The Template string will store an HTML string into which the dynamic view will be injected. Essentially the Template can be used to save the ‘Master Page’ of our View. We will later see what keywords we can use to serve as the placeholder for the dynamically generated HTML.

public class DataForm
{
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    [Required]
    public string Description { get; set; }

    public string Template { get; set; }

    public List<DataField> Fields { get; set; }
}

Each DataField will save

- The Field Type like Input Text Boxes, Selection Options, Check Boxes, Images etc.

- It will store the display label for these and the Max Length

- Flag indicating whether these fields are mandatory or not.

- We also have a ‘Foreign Key’ reference to a Data

public class DataField
{
    public int Id { get; set; }
    [Required]
    public string FieldName { get; set; }
    [Required]
    public string DisplayLabel { get; set; }
    [Required]
    public FieldType DisplayType { get; set; }
    [Required]
    public bool IsMandatory { get; set; }
   
    public int FormId { get; set; }
    [ForeignKey("FormId")]
    [ScriptIgnore]
    public DataForm ParentForm { get; set; }
}

The FieldType enum is defined as follows. We can save the class file in the Models\Core folder itself


public enum FieldType
{
    TextBox,
    TextArea,
    DropDown,
    CheckBox,
    Label
}

Saving a View – The Core Controllers and Views

Once the Entities are setup, we’ll create a Core folder and add the DataForm and DataField Controllers using the MVC Tooling. We’ll use Entity Framework as the backend.

data-form-and-field-controller

That completes the CRUD support for the Core Form Entities. So we can now go and define some Forms for ourselves.

Creating a DataForm

Our First Template will be a Blog Template that we define as follows

mvc-data-template

As we can see above, the Template field is most interesting. We’ve specified a rudimentary HTML skeleton with the key word ‘@DataFields’. This key word will be replaced by the markup for the Fields that is generated at runtime. So next let us see how we define the Fields themselves.

Creating Data Fields for the Form

For the Blog Template we will have three fields - Title, Author and Post. Following shows creation of the “Post” field

create-data-field

Once all three fields are created, the DataField Index page is as follows:

data-fields

So now we have defined one form in our database. It is for creating Blog Post entries and has three entry fields: Title, Post and Author. This is an oversimplification for the purpose of this article, but as I mentioned, we can make this as complicated as we want. Let’s continue with the proof of concept.

Loading View Definition into View Engine

Now that our View has been defined and stored in the Database, let’s see how we can retrieve it and render it into a View.

Updating the Custom View

1. In the DbDrivenView class declare an instance of DataDrivenViewEngineContext.

2. Next add a Constructor that takes in the View Name. This will have to match our Template’s Name property.

3. In the Render method, we’ll use the View Name property to pull up the Template and its Fields. Next we will loop through the Fields and render them using the TextWriter that was passed on to the Render method.

The Updated Class is as follows

public class DbDrivenView : IView
{
DataDrivenViewEngineContext dbContext = new DataDrivenViewEngineContext();
string _viewName;
public DbDrivenView(string viewName)
{
  if (string.IsNullOrEmpty(viewName))
  {
   throw new ArgumentNullException("viewName", new ArgumentException("View Name cannot be null"));
  }
  _viewName = viewName;
}
public void Render(ViewContext viewContext, TextWriter writer)
{
  DataForm form = dbContext.DataForms.Include("Fields").First(f => f.Name == _viewName);
  HtmlTextWriter htmlWriter = new HtmlTextWriter(writer);
  htmlWriter.RenderBeginTag(HtmlTextWriterTag.Div);
  foreach (var item in form.Fields)
  {
   htmlWriter.RenderBeginTag(HtmlTextWriterTag.Div);
   htmlWriter.WriteEncodedText(item.DisplayLabel);
   htmlWriter.RenderBeginTag(GetHtmlRenderKey(item.DisplayType));
   htmlWriter.RenderEndTag();
   htmlWriter.RenderBeginTag(HtmlTextWriterTag.Div);
  }
  htmlWriter.RenderEndTag();
}
private HtmlTextWriterTag GetHtmlRenderKey(FieldType fieldType)
{
  switch (fieldType)
  {
   case FieldType.TextBox:
    return HtmlTextWriterTag.Input;
   case FieldType.TextArea:
    return HtmlTextWriterTag.Textarea;
   case FieldType.DropDown:
    return HtmlTextWriterTag.Select;
   case FieldType.CheckBox:
    return HtmlTextWriterTag.Input;
   case FieldType.Label:
    return HtmlTextWriterTag.Caption;
   default:
    return HtmlTextWriterTag.Unknown;
  }
}
}

Updating the Custom View Engine

Now that we have a constructor that takes one parameter, we will have to update the View Engine to pass the parameter. We will also change the Condition to use our view. Instead of checking for the ViewName to be Dynamic, we’ll check if the Route has the string “Dynamic”.

public ViewEngineResult FindView(
    ControllerContext controllerContext,
    string viewName, string masterName, bool useCache)
{
if (controllerContext.RouteData.Values.ContainsValue("Dynamic"))
{
  return new ViewEngineResult(new DbDrivenView(viewName), this);
}
else
{
  return new ViewEngineResult(new string[]
  { @"No Suitable view found for 'DbDataViewEngine',
   please ensure View Name contains 'Dynamic'"
  });
}
}

Once these two changes are in place, we can run the application to check it out. The only condition is that the Route should have the value Dynamic in it. So we add an Action method in HomeController called Dynamic with the input being the view name that we want to render

public ViewResult Dynamic(string id)
{
    return View(id);
}

Now run the application and navigate to the URL http://localhost:[your port]/Home/Dynamic/BlogTemplate/

Voila! We get this!

aspnet-mvc-custom-engine-update

If you just cringed and went “eww…” at the HTML nightmare above, I hear you. Also if you were paying attention you’ll realize we didn’t use the DataForm’s Template field value. Let’s see how we can stuff our rendered HTML into the Template and then how to make the template better.

Adding some Styling and Eye Candy

First we update the custom View’s Render method to use a StringWriter so that we can write the dynamic string independent of the TextWriter instance sent to us. Once we are done writing to the StringWriter, we replace the “@DataFields” token with this generated string. Finally we write this string out to the TextWriter instance of the Render method.

public void Render(ViewContext viewContext, TextWriter writer)
{
DataForm form = dbContext.DataForms.Include("Fields").First(f => f.Name == _viewName);
var sb = new StringBuilder();
var sw = new StringWriter(sb);
using (HtmlTextWriter htmlWriter = new HtmlTextWriter(sw))
{
  htmlWriter.RenderBeginTag(HtmlTextWriterTag.Div);
  foreach (var item in form.Fields)
  {
   htmlWriter.RenderBeginTag(HtmlTextWriterTag.Div);
   htmlWriter.WriteEncodedText(item.DisplayLabel);
   htmlWriter.RenderBeginTag(GetHtmlRenderKey(item.DisplayType));
   htmlWriter.RenderEndTag();
   htmlWriter.RenderBeginTag(HtmlTextWriterTag.Div);
  }
  htmlWriter.RenderEndTag();
}
writer.Write(form.Template.Replace("@DataFields", sb.ToString()));
}

Now we go back to DataForm template definition and update the Template to be as follows

<!DOCTYPE html>
<link href="/Content/site.css" rel="stylesheet"/>
<html lang="en">
<body>
  <header>
   <div class="content-wrapper">
    <p class="site-title">Blog Template</p>
   </div>
  </header>
  <div id="body">
   <section class="content-wrapper main-content clear-fix">
   @DataFields
   </section>
  </div>
</body>
</html>

As we can see, we have utilized the existing CSS that we get in the ASP.NET Project template.

modified-data-form-template

And the Result? Here you go! Nice eh!

mvc-final-view

Submitting the Form Data

Well, we have the Form, we have some styling, but we don’t have a way to submit the data that user fills in the form. We could do multiple things here:

a. We could update the Form Fields to add a button and then do AJAX Posts or

b. Add another property to our Form called Submit Data that will take a URL to which we should Submit Data. Let’s see what it takes to submit the Form Data.

Updating the DataForm Entity

Let’s update the DataForm entity and also visit some of the things I didn’t talk about earlier but I already did, to get the sample working.

The modified DataForm Entity

I have highlighted the changes in the code below:

1. We have a backing field called _template that stores the Template html string.

2. The Template property is decorated with the [AllowHtml] attribute. If we don’t do this then ASP.NET MVC will throw an error saying suspicious characters detected. This is to prevent XSS hacks via unprotected Inputs. In our case we genuinely need HTML to come through, so we’ll let it come in, but before assigning it to the backing store we will sanitize it using HttpUtility.HtmlEncode(…) method.

3. Since the data being saved is HtmlEncoded, when returning the data we’ve to return it HtmlDecoded.

public class DataForm
{
    string _template;
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    [Required]
    public string Description { get; set; }
    [DataType(DataType.MultilineText)]
    [AllowHtml]
    public string Template
    {
        get
        {
            return HttpUtility.HtmlDecode( _template);
        }

        set
        {
            string sanitized = HttpUtility.HtmlEncode(value);
            _template = sanitized;
        }
    }

    public List<DataField> Fields { get; set; }
    public string SubmitUrl { get; set; }
    public string SubmitName { get; set; }

}

4. To make our Encoding more secure, we will use the AntiXSS Library to do the Encoding. For that we don’t need any change to the HttpUtility.HtmlEncode(…) call. Instead we plug in the AntiXSS library in the Web.config as follows

<httpRuntime
targetFramework="4.5"
encoderType="System.Web.Security.AntiXss.AntiXssEncoder,
              System.Web, Version=4.0.0.0, Culture=neutral,
              PublicKeyToken=b03f5f7f11d50a3a"/>

In .Net 4.5 you will have the httpRuntime node with the targetFramework attribute already. Add the encoderType as shown above to plug in the AntiXssEncoder as the default Encoder. HttpUtility will now use this.

Point 3 and 4 here are actually required to do the demo so far. So I had already done this to run our Demo.

5. Now we add two new properties SubmitUrl and SubmitName. They are self-explanatory, one stores the Label of the Button and the other Stores the URL to which we shall post the Data.

With these changes clarified. Let’s go to our Custom View generator and see what it takes to render the additional markup to make our View into a Submit-able HTML Form.

6. We update the respective Index/Create and Edit pages to Read/Create and Update the new fields. The following screen shows the edit screen for our current Template.

updated-data-form-with-submit-details

Note: When you add new fields to a Database that you are posting data to using Entity Framework, EF will protest when the Schema changes. You have to use EF Migrations to update your database after you add properties to the DataForm entity.

Updating the Custom View – DbDrivenView

With the new fields in place, we use them to render the appropriate Form tags and the Submit button to post the data to the controller.

I have tagged portions of the code below for reference.

#1: We add the Form Tag and add the action and method attributes to it. The action attribute gets the value of the ‘SubmitUrl’ property. We have a check for Empty on the SubmitUrl property so if there is no SubmitUrl, then we don’t create the Form. Section #3 does the same check before adding the Form’s end tag.

#2: The fields that we are showing in our view must have an ‘id’ and ‘name’ set. We were not utilizing the FieldName property of our DataField objects. Now we will use this to populate the Id and Name attribute of the Field.

Notice a peculiarity of HtmlWriter’s AddAttribute property. Since the writer is forward only cursor you have to declare the attributes before you render the begin tag using RenderBeginTag method.

#3: If the SubmitName property is populate we add the Submit button to the Form as well.

public void Render(ViewContext viewContext, TextWriter writer)
{
DataForm dataForm = dbContext.DataForms.Include("Fields").First(f => f.Name == _viewName);
var sb = new StringBuilder();
var sw = new StringWriter(sb);
using (HtmlTextWriter htmlWriter = new HtmlTextWriter(sw))
{
  // #1 Begins
  if (!string.IsNullOrEmpty(dataForm.SubmitUrl))
  {
   htmlWriter.AddAttribute("action", dataForm.SubmitUrl);
   htmlWriter.AddAttribute("method", "post");
   htmlWriter.RenderBeginTag(HtmlTextWriterTag.Form);
  }
  // #1 Ends
  htmlWriter.RenderBeginTag(HtmlTextWriterTag.Div);
  foreach (var item in dataForm.Fields)
  {
   htmlWriter.RenderBeginTag(HtmlTextWriterTag.Div);
   htmlWriter.WriteEncodedText(item.DisplayLabel);
   // #2 Begins
   htmlWriter.AddAttribute(HtmlTextWriterAttribute.Id, item.FieldName);
   htmlWriter.AddAttribute(HtmlTextWriterAttribute.Name, item.FieldName);
   // #2 Ends
   htmlWriter.RenderBeginTag(GetHtmlRenderKey(item.DisplayType));
   htmlWriter.RenderEndTag();
   htmlWriter.RenderBeginTag(HtmlTextWriterTag.Div);
  }
  // #3 Begins
  if (!string.IsNullOrEmpty(dataForm.SubmitUrl))
  {
   htmlWriter.RenderEndTag();
  }
  // #3 Ends
  // #4 Begins
  if(!string.IsNullOrEmpty(dataForm.SubmitName))
  {
   htmlWriter.AddAttribute("type", "submit");
   htmlWriter.AddAttribute("value", dataForm.SubmitName);
   htmlWriter.RenderBeginTag(HtmlTextWriterTag.Input);
   htmlWriter.RenderEndTag();
  }
  // #4 Ends
  htmlWriter.RenderEndTag();
}
writer.Write(dataForm.Template.Replace("@DataFields", sb.ToString()));
}

Updating the Controller to receive the HttpPost

We make two changes to the HomeController class

1. We decorate the existing Dynamic action method with the attribute [HttpGet] as follows

[HttpGet]
public ViewResult Dynamic(string id)
{
    return View(id);
}

2. Next we add another Dynamic action method for handling the HttpPost as follows

[HttpPost]
public ActionResult Dynamic(string id, FormCollection collection)
{
    return View(id);
}

Testing it Out

1. To test the Posting of data, we put a breakpoint in the newly added Action method and navigate to our View.

save-dynamic-form

2. Populate some data and hit Submit. As we hit the breakpoint, we add the FormCollection to the watch list and expand it. We can see the collection has three keys corresponding to the three fields with the exact same names as provided in FieldName of our Dynamic fields. Lastly we see that the values that we posted from above, have come through correctly in the controller!

Awesome!

debug-view-engine

In Conclusion – Lots more to do

We saw how to build a new Custom View Engine, Custom IView implementation, we built a dynamic form and we used the Dynamic Form to submit data back as well. However we have only scraped the surface of building a full-fledged View Engine. We haven’t touched upon vital pieces like caching, DataBinding and Validation. We leave these for another day or if you are getting into the groove, you can send pull requests to our GitHub repo and send across your additions for publication.

We conclude this chapter of View Engine Creation here today. Even if you don’t need to do this ever, hope it gave you a clearer picture of how the View Engines in the ASP.NET MVC Framework work.

Download the entire source code of this article (Github)

Give me a +1 if you think it was a good article. Thanks!
Recommended Articles
Sumit is a .NET consultant and has been working on Microsoft Technologies since his college days. He edits, he codes and he manages content when at work. C# is his first love, but he is often seen flirting with Java and Objective C. You can follow him on twitter at @sumitkm or email him at sumitkm [at] gmail


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by Zaib on Tuesday, November 12, 2013 2:12 AM
Though the article is truly excellent, you have missed on the most important aspect of how to save the dynamic FormCollection to database.
Most of the queries on  the web do not recommend using FormCollection.
If you can provide a working solution to this problem, that will be excellent. My search for the same has gone in vain.
Comment posted by Sumit on Tuesday, November 12, 2013 10:19 AM
"Most of the queries on the web do not recommend using a FormCollection" is a rather thin argument when you are working with the guts of HTML rendering like in this case.

A form collection is basically collection of name/value pairs. How you want to save it to a database is dependent on your use case. In the above  scenario I would have a Table with four columns - ID (PK), TemplateID [FK], FieldID and FieldValue. So there will be one row of data for each field e.g.
[1, 1, "Title", "My First Post"],
[2, 1, "Author", "You Know Who"],
[3, 2, "Post", "yada yada yada"]

In a real life scenario I have used Knockout Databinding and Posted JSON objects instead of doing Form Post, so that's another option you can explore. Explaining that is beyond the comment section I am afraid.
Comment posted by Sumit on Tuesday, November 12, 2013 12:11 PM
CORRECTION: the Sample Data should be

[1, 1, "Title", "My First Post"],
[2, 1, "Author", "You Know Who"],
[3, 1, "Post", "yada yada yada"]

(we are saving values for the same Template so TemplateID remains the same for all rows).
Comment posted by Sekhar on Sunday, January 26, 2014 5:18 AM
Wonderful article, one of the best I read in some time.

@Zaib - not fair to have come to a wrong place and claim that he has missed what you wanted. As the title says, the article is about how to make use of view engine extensibility in MVC.
Comment posted by Chetan on Tuesday, February 18, 2014 1:14 AM
Wow nice work.
But I want to sent more then 1 parameter to "GET" method but url look like following:
"/Home/Dynamic/BlogTemplate/View"
"/Home/Dynamic/BlogTemplate/Add"
"/Home/Dynamic/BlogTemplate/Edit"
"/Home/Dynamic/BlogTemplate/Delete"

So can you please help me to resolve.
Comment posted by Validation on Thursday, February 27, 2014 5:43 PM
Hello any idea how to do validation for data driven view?
Comment posted by Jackboy70 on Friday, March 7, 2014 2:50 PM
Is it possible to export the script of your database file? The database is not compatible with pre-2012 version of SQLServer! Thanks !
Comment posted by Jackboy70 on Sunday, March 9, 2014 12:06 AM
/****** Object:  Table [dbo].[DataForms]    Script Date: 03/09/2014 01:00:52 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[DataForms](
   [Id] [int] IDENTITY(1,1) NOT NULL,
   [Name] [varchar](max) NOT NULL,
   [Description] [varchar](max) NOT NULL,
   [Template] [varchar](max) NOT NULL,
   [SubmitName] [varchar](max) NOT NULL,
   [SubmitUrl] [varchar](max) NOT NULL,
CONSTRAINT [PK_DataForms] PRIMARY KEY CLUSTERED
(
   [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object:  Table [dbo].[DataFields]    Script Date: 03/09/2014 01:00:52 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[DataFields](
   [Id] [int] IDENTITY(1,1) NOT NULL,
   [FieldName] [varchar](max) NOT NULL,
   [DisplayLabel] [varchar](max) NOT NULL,
   [DisplayType] [int] NOT NULL,
   [IsMandatory] [bit] NOT NULL,
   [FormId] [int] NOT NULL,
CONSTRAINT [PK_DataFields] PRIMARY KEY CLUSTERED
(
   [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object:  ForeignKey [FK_DataFields_DataForms]    Script Date: 03/09/2014 01:00:52 ******/
ALTER TABLE [dbo].[DataFields]  WITH CHECK ADD  CONSTRAINT [FK_DataFields_DataForms] FOREIGN KEY([FormId])
REFERENCES [dbo].[DataForms] ([Id])
GO
ALTER TABLE [dbo].[DataFields] CHECK CONSTRAINT [FK_DataFields_DataForms]
GO
Comment posted by Jackboy70 on Wednesday, March 12, 2014 8:12 PM
/****** Object:  Table [dbo].[DataForms]    Script Date: 03/09/2014 01:00:52 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[DataForms](
   [Id] [int] IDENTITY(1,1) NOT NULL,
   [Name] [varchar](max) NOT NULL,
   [Description] [varchar](max) NOT NULL,
   [Template] [varchar](max) NOT NULL,
   [SubmitName] [varchar](max) NOT NULL,
   [SubmitUrl] [varchar](max) NOT NULL,
CONSTRAINT [PK_DataForms] PRIMARY KEY CLUSTERED
(
   [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object:  Table [dbo].[DataFields]    Script Date: 03/09/2014 01:00:52 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[DataFields](
   [Id] [int] IDENTITY(1,1) NOT NULL,
   [FieldName] [varchar](max) NOT NULL,
   [DisplayLabel] [varchar](max) NOT NULL,
   [DisplayType] [int] NOT NULL,
   [IsMandatory] [bit] NOT NULL,
   [FormId] [int] NOT NULL,
CONSTRAINT [PK_DataFields] PRIMARY KEY CLUSTERED
(
   [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object:  ForeignKey [FK_DataFields_DataForms]    Script Date: 03/09/2014 01:00:52 ******/
ALTER TABLE [dbo].[DataFields]  WITH CHECK ADD  CONSTRAINT [FK_DataFields_DataForms] FOREIGN KEY([FormId])
REFERENCES [dbo].[DataForms] ([Id])
GO
ALTER TABLE [dbo].[DataFields] CHECK CONSTRAINT [FK_DataFields_DataForms]
GO
Comment posted by Greg on Tuesday, April 1, 2014 11:59 AM
Jacky, thanks for the DB script!
Comment posted by Chetan Ramesh Chaudhari on Sunday, April 20, 2014 11:56 PM
I done my all project functionality using Data Driven View Engine with business logic.
Thanks Sumith Sir

Thanks, Chetan

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel