views:

92

answers:

1

Updated:

This is a re-write from my original question (or lack of), the main problem I am having at the moment is that when mapping my Widget domain models to the correct ViewModel I am having to do it like this which is definetly not the right solution...

public ProfileWidgetViewModel MapFrom(ProfileWidget input, Account userAccount)
    {
        ProfileWidgetViewModel viewModel = Mapper.Map<ProfileWidget, ProfileWidgetViewModel>(input);

        viewModel.IsLoggedIn = identityTasks.IsSignedIn();

        // we need to use the correct mapper depending on the widget
        switch(input.GetType().Name.ToLower())
        {
            case "htmlwidget":
                viewModel.ProfileWidgetItem = htmlWidgetViewModelMapper.MapFrom((HtmlWidget)input);
                break;

            case "mediawidget":
                viewModel.ProfileWidgetItem = mediaWidgetViewModelMapper.MapFrom((MediaWidget)input, userAccount);
                break;
}

        return viewModel;
    }

Because I am passing in the BaseClass (even though I know I can safely downcast the correct type), I am needing to do a big switch statement to map the Widget viewmodel using the correct class.

I need somehow to make this more dynamic so it can automatically pickup the correct class to use, i'm sure there is a way using generics / reflection to do this, i'm open to suggestions if you think I am going about this the wrong way.

+1  A: 

I recommend not to use pop-up windows but to use some modal windows for a page, like jqModal. IMO it's better for usability than native pop-ups.
About your widgets, what about to look at the problem from the side of a models? For a widget you'll have 2 view models - one for displaying and one for editing settings of the widget. It's better to have 2 different controllers for displaying a widget and for editing settings (I cast SRP principle here). So the first controller will return a widget data model and the second - settings data model. And views, you can use as much as you need, it's hard to recommend something here using only words and without custom implementation of the project in mind.
It's hard to try to answer a vague question. May be you should ask some more specific questions? And check this sample of a portal with widgets, it uses ExtJS library that's very easy to learn and use and it's very powerful.

Edit 02/20/10:
I prefer to use the following approach (I'll use a widget with name FooWidget for example). Create 2 controllers with names FooWidgetDataController and FooWidgetSettingsController. Add routes for urls:

/widgets/FooWidget/data for FooWidgetDataController
/widgets/FooWidget/settings for FooWidgetSettingsController

Create FooWidgetDataModel:

public class FooWidgetDataModel {
    public int Column1 {get; set;}
    public int Column2 {get; set;}
    public int Column3 {get; set;}
}

In the FooWidgetDataController fill the FooWidgetDataModel and return it to some view:

public class FooWidgetDataController : Controller {
    public ActionResult Index(){
        var model = new FooWidgetDataModel{ Column1=5, Column2=1  }; // loading of data for FooWidgetDataModel
        return View(model); // using a view with name Index.ascx or Index.aspx
    }
}  

Create FooWidgetSettingsModel:

public class FooWidgetSettingsModel {
    public bool ShowColumn1 {get; set;}
    public bool ShowColumn2 {get; set;}
    public bool ShowColumn3 {get; set;}
}

And sample code for FooWidgetSettingsController:

// add some permission verification attribute here
public class FooWidgetSettingsController : Controller {
    [AcceptGet]
    public ActionResult Index(){
        var model = new FooWidgetSettingsModel{ ShowColumn1=true, ShowColumn2=false  }; // loading of data for FooWidgetSettingsModel
        return View(model); // using a view with name Index.ascx or Index.aspx
    }

    [AcceptPost, ActionName("Index")]
    public ActionResult IndexPost(FooWidgetSettingsModel model){ // model will be automatically binded by built it functionality
        // validate model
        // save settings if valid
        // and return whatever you want here
        return RedirectToAction("Index"); // for example, redirecting to edit page
    }
}

Using this approach you'll need to create a controller per widget. Probably you'll not like it but using some extensions or base classes you will not need to write a lot of code. And code will be easy to read and simple.
For rendering a widget on a page consider using Html.RenderAction (previously it was in mvc futures assembly, I don't track changes at the moment).
Note, keep your controllers as thin as possible and check some best practices for asp.net mvc (link 1 and link 2).

zihotki
Hi thank you for the answer, after reading it back my question is very vague, I rewrote it 3 times initially because I thought it was too large and asking too many questions.I think I am going to break it down into bitesize questions. I am using Model windows currently, and have 2 ViewModels as you say. I am editing my question now to reflect my new question.
Paul Hinett
I like this implemenation...however if each widget now has it's own controller, when i'm looping through each of my widgets to display in my Profile page view, how can i call RenderAction<T> for that type of widget...there maybe 10+ different types of widgets all on one page. If i can get that working then I will be very happy with the outcome!
Paul Hinett
@Paul, you can define some interface like IWidget with method Render. Each widget should implement this interface and in implementation of the Render just use custom RenderAction with required parameters. So later you can just place all widgets in collection and place them in view.
zihotki