1

I'm working with ASP.NET MVC 2 and building a simple business app. Here are some of the details:

  • The app deals with work orders and has a work order index view. The view has a table listing the work orders, and several controls (text boxes, check boxes, and drop down lists) to select the criteria for which work orders to display.

  • I'm using viewmodels. The work order index view has a viewmodel with properties for each and every control.

  • I've implemented paging similar to what is being done in the answer to this question: How do I do pagination in ASP.NET MVC? I'm using LINQ's Skip() and Take() as demonstrated, and ActionLinks for the navigation.

  • If I load the page and don't manipulate any of the controls, I can click on the page number ActionLinks and move around just fine between pages of work orders. However, if I change something, my changes are lost when I navigate to another page.

    For example, if I'm on page 1 and click an unchecked check box, and then click on the link for page 2, the second page of results will load but the check box will revert to its previous state.

I understand why this happens, but I'm wondering what is the best thing to do from a design standpoint.

Potential solutions I can think of:

  1. Set all the control values as route values in the ActionLinks. This seems really nasty, and could result in very long URLs or query strings. Actually, now that I think of it this wouldn't work without a way to capture the control values.

  2. Since ActionLinks don't post anything, replace them with buttons. Again, this seems like a bad idea.

  3. Change the ActionLinks to links that fire off a jQuery script that does a POST. I think this is the most promising option so far. Do many developers do it this way?

This seems like a common enough problem, but none of these options feel quite right. I wonder if I'm missing something.

Community
  • 1
  • 1
Andy West
  • 12,302
  • 4
  • 34
  • 52

3 Answers3

0

Can't you just save the changes back to the database when the user toggles the checkboxes (using jQuery):

$("input[type=checkbox]").click(function() {
     $.ajax({
          type: "POST",
          url: "/ControllerName/SaveInfo?id=" + {id},
          success: function(){
                alert("Data Saved: " + msg);
          }
     });
});
Robert W
  • 2,921
  • 7
  • 34
  • 42
  • No, I don't want to store the state of my controls in a database; that would be inefficient. I did, however, use jQuery in the end. – Andy West Dec 03 '10 at 20:07
0

In the end, I wound up getting rid of the ActionLinks for the paging, and replaced them with regular anchor tags. The current page index is now stored in a hidden form value:

<input id="page" name="page" type="hidden" value="" />

<p>
    <% for (var i = 1; i <= (int)Math.Ceiling(Model.RowsMatchingCriteria / (double)Model.PageSize); i++) { %>

        <%--
            If the page number link being rendered is the current page, don't add the href attribute.
            That makes the link non-clickable.
        --%>
        <a class="pageLink" <%= i != Model.Page ? @"href=""javascript:void(0);""" : string.Empty %>><%: i %></a>

    <% } %>
</p>

Then I added the following jQuery script, which sets the hidden page value and submits the form when a link is clicked:

$(document).ready(function () {

    $('.pageLink:[href]').click(function () {
        $('#page').val($(this).text());  // Set hidden field value to the text of the page link, which is the page number.
        $('form:first').submit();
    });

});

Problem solved.

Andy West
  • 12,302
  • 4
  • 34
  • 52
0

Best bet is to effectively simulate viewstate by "logging" the changes to a hidden field when a user paginates. To do so:

1) Figure out what data you need to capture and a data format to do so in {ie -- an array of json objects} 2) Setup the link that handles the prev/next to fire off a method to collect the "changed" things and stuff them into objects and into a hidden field.
3) When posting the form, parse the hidden field, extract data and profit.

Wyatt Barnett
  • 15,573
  • 3
  • 34
  • 53
  • Please see my answer above. What I did is somewhat similar to this, except most of it automatic due to ASP.NET MVC's "convention over configuration." The hidden field (and all the other from controls) have corresponding properties in the viewmodel. So when I do a submit, they're linked up automagically. – Andy West Dec 03 '10 at 23:03
  • Yes, it is somewhat similar, but you are still POSTing GET requests effectively, which is kind of self defeating. – Wyatt Barnett Dec 04 '10 at 01:25
  • I don't know what you mean by POSTing a GET request. I'm definitely doing a post - the action method is even decorated with the HttpPost attribute. There are no GETs involved as far as I understand it. – Andy West Dec 04 '10 at 03:48