views:

425

answers:

5

hi-

i'm working on designing an asp.net mvc web app. There will be half a dozen (maybe more to come) different user groups of the app and they all work with similar but tweaked UIs, each with a few custom fields but all using the same objects.

one idea for creating the UI is to store Control info with each field value in the database, and construct each view completely when we query the database.

this sounds like a flexible way to create the Views without having to define a separate set of views for each user group, since each screen could have different fields depending on user group.

It also sounds like it will be hard to control the layout.

My question: is this a correct approach? Where's the middle ground between creating a drag+drop layout and driving the entire UI off DB fields?

thanks!!

+1  A: 

If your views are simple (flat, without nested subcontrols) this may make sense. MVC v2 supports something like this with Html.InputFor(), similar thing is implemented for MVC v1 in InputBuilder from MvcContrib. They all iterate through model properties using reflection and create appropriate controls (i.e. textbox for string, checkbox for boolean, etc).

However I'd say that for more complext views this will fail. For example, currently MVC v2 has problems doing this InputFor for IList. But if you can take the idea (and MVC sources are available, as well as InputBuilder ones) and tweak it as needed for your project. I think only you can decide if automated generation can work for you.

queen3
+1  A: 

Personally, I would go for the separately defined views. Of course, I say that without knowing how complex the individual views would be. My rationale has mostly to do with making the layouts work, which you are correct in saying would be harder using generated views.

If there is a great deal of commonality between the views (and why wouldn't there be, since they are using the same app), you should be able to factor those items into partial views and leave the customization to the deltas for each user group.

KevDog
A: 

MVC has a much stronger focus on semantic HTML code and HTML is built for layouts that flow. Well designed and styled controls should not pose a problem, especially with a data driven design.

For example look at this site, the main content is any number of answers to a question (with and without comments), the question itself, ads, buttons, etc.

Also consider sites like iGoogle that let you layout the page dynamically (really you are switching the order and containers of elements in a flow layout).

Future Drag and Drop and other Eye candy can be implemented with CSS, JavaScript and JQuery or other Web2.0/Ajax UI/UX frameworks.

To put it simply, ASP.net MVC was designed to fill this kind of need; dynamic, data driven web apps that don't benefit from replicating WinForms on the Web.

Adam Tolley
+1  A: 

If you are able to use the Preview 2 of MVC 2 then you could accomplish this by inheriting from DataAnnotationsModelMetadataProvider, or ModelMetadata if you don't want the attribute based stuff at all.

Then you would want to override the CreateMetadata method like:

public class MyMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
        ModelMetadata metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
        bool show = true;
        /* Code to check if the fields should show */

        metadata.ShowForDisplay = show;
        metadata.ShowForEdit = show;
        return metadata;
    }
}

Then on your generic view do just call the .DisplayFor<> or .EditorFor<> like shown here http://weblogs.asp.net/scottgu/archive/2009/07/31/asp-net-mvc-v2-preview-1-released.aspx.

Update:

You would also need to set the ModelMetadataProviders.Current = new MyMetadataProvider();

Sean Lynch
A: 

Usually I would lean towards separate views but in this situation I think one view might be easier. I would do it something like this:

public class YourClass
{
    public string Property1 { get; set; }

    public int Property2 { get; set; }

    public DateTime Property3 { get; set; }
}

// ViewData for YourClass
public class YourClassViewData
{
    public YourClass YourClass { get; set; }

    public bool Property1Visible { get; set; }

    public bool Property2Visible { get; set; }

    public bool Property3Visible { get; set; }
}

// Use this inside your controller to
// build appropriate View data based on group or user
public classYourClassViewDataBuilder
{
    // not sure on what your using for user stuff but you can
    // change that. You should get the idea though...
    public static YourClassViewData BuildYourClassViewData(string user, YourClass yourClass)
    {
        YourClassViewData result = new YourClassViewData();
        result.YourClass = yourClass;

        if (user == "ViewOnly")
        {
            result.Property1Visible == false;
            result.Property2Visible == true;
            // etc.
        }
        else if (user == "Admin")
        {
            reslut.Poperty1Visible == true;
            // etc.
        }

        return result;
    }
}

// Then inside your view your would just do it like this...
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<YourClassViewData>" %>

<% if (Model.Property1Visible)
{ %>
    <label for="Property1">
    Property1:</label>
    <% Html.RenderYourControl("Property1", Model.YourClass.Property1) %>
<% } %>

<!-- continue for each property... -->
J.13.L