Simon Martin
Simon Martin

Reputation: 4231

MVC page that displays multiple, related, ViewModels updating with ajax

I have some simple list management pages, each is strongly typed against the following ViewModel

public class ListManagementIndexViewModel
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

I have Views for Category, Priority, Status and a few other drop downs, there's some AutoMapper configuration that ensures the Name property is bound to whatever the Domain model might have for the entity. The idea is that the systems administrators are able to manage what's in these lists (Create new, Edit existing and Delete). This gives me an Index view for each like this:

Priority list management

I would like to put all of these on a single page, rather than have separate views for each. I think partials are probably the way to do this, but I'm not clear whether that's a recommended approach or not?

Also I'm not clear on how to handle the Controller(s). As things stand; with the PriorityController I have the following Index ActionResult

public ActionResult Index(string searchString, string currentFilter, int? page)
    {
        if (Request.HttpMethod == "GET")
            searchString = currentFilter;

        ViewBag.CurrentFilter = searchString;
        int pageNumber = page ?? 1;

        var query = Session.QueryOver<Priority>();

        if (!string.IsNullOrWhiteSpace(searchString))
            query.WhereRestrictionOn(p => p.PriorityName)
                 .IsInsensitiveLike(String.Format("%{0}%", searchString));

        var result = query.OrderBy(p => p.PriorityName).Asc.List();

        var viewModel = AutoMapper.Mapper.Map<IEnumerable<Priority>, 
                          IEnumerable<ListManagementIndexViewModel>>(result)
                                  .ToPagedList(pageNumber, PageSize);

        return View(viewModel);
    }

While I could move that to a 'Master' single list management page I would also need to do the same for the other list types, but then what would my ViewModel need to look like, there are currently 5 lists to manage, so I have 5 controllers doing exactly the same thing, only the types vary. If I were to put all that on 1 'Master' single view page I would somehow need to stuff all 5 PagedList collections into 1 ViewModel and then in the 'Master' single version pass the data off to the relevant Partials razor code?

Also how would I handle the other Controller actions (Edit, Create and Delete)?

Update
Thinking on my feet - if the unified / single view page ViewModel were:

public class ListManagementIndexViewModel
{
    public Dictionary<string, IPagedList<T>> ManagementLists { get; set; }
}

and the SinglePageController were

public ActionResult Index(string searchString, string currentFilter, int? page)
{
    var priorities = GetPriorities(searchString, currentFilter, page);
    var categories = GetCategories(searchString, currentFilter, page);

    Dictionary<string, IPagedList> viewModel
       = new Dictionary<string, IPagedList<T>>();

    viewModel.Add("Priorities", priorities);
    viewModel.Add("Categories", categories);
    return View(viewModel);
}

I could move the existing logic out to a private method

private IPagedList<Priority> GetPriorities(string searchString, 
                                           string currentFilter, int? page) 
{
    if (Request.HttpMethod == "GET")
        searchString = currentFilter;

    ViewBag.CurrentFilter = searchString;
    int pageNumber = page ?? 1;

    var query = Session.QueryOver<Priority>();

    if (!string.IsNullOrWhiteSpace(searchString))
        query.WhereRestrictionOn(p => p.PriorityName)
             .IsInsensitiveLike(String.Format("%{0}%", searchString));

    var result = query.OrderBy(p => p.PriorityName).Asc.List();

    var priorities = AutoMapper.Mapper.Map<IEnumerable<Priority>, 
                          IEnumerable<ListManagementIndexViewModel>>(result)
                                  .ToPagedList(pageNumber, PageSize);

    return priorities;
}

Then in my View the model would contain the ManagementLists collections and I could foreach the results into html tables as I'm currently doing but on separate pages.

However a paging through the results would then result in all lists tables paging rather than just the Priorities table. How would I make each update with Ajax, so paging in one table would only update the list in that one table? If I were to re-include searching, which is currently in the ActionResult method, but not implemented in the UI that would also need to update just the Priorities table. For example if I entered "High" in the search for Priority I would only want to query the Priority table and update it and not run 5 queries to the database to search for "High" in Category or any of the other lists.

Upvotes: 2

Views: 448

Answers (1)

Mathew Thompson
Mathew Thompson

Reputation: 56429

I think you should only use a partial if you intend to use it again. I see too often people creating them to help break down the code, but they're never used again.

It would be more organised to have the 5 lists under the one page, that way they're all in the one model and are centrally managed by one controller/model.

Upvotes: 2

Related Questions