How to change WebGrid action for getting data (.NE

2020-06-04 10:43发布

问题:

I have a Partial View that renders WebGrid. My controller looks like

public ActionResult Index()
{
    return View();
}
public ActionResult GetUserList(int? page, string sort, string sortdir)
{
    var model = UserModel.getList(page,sort,sortdir);
    return PartialView("_UserList",model);
}

Index.cshtml :
....
@Html.Action("GetUserList")

The problem is that every time I click on grid navigation or sort links it calls Index method. How can I make Webgrid to execute a different action (GetUserList in this case)? I'm sure I can prepend GetUserList to all links in grid using jquery, but I believe it should be a better way.
It's also possible that what I'm doing is completely wrong, so thanks for your suggestions.

回答1:

After lot of monkeying around and digging (and even fiddling with Reflector with WebGrid's source code), I came to the conclusion that with WebGrid, you cannot control/change the Header link action.

To create the header link URL, the path is taken from HttpContext.Request.Path, so there is no way to customize it to point to a different route.

One very ugly hack would be to tap into to jQuery Ajax's events (since the header link uses jQuery.load to sort) and overwrite the URL:

<a href="#" onclick="$('#myGrid').load('/?sort=AlbumId&amp;sortdir=ASC&amp;__=634486582282704242 #myGrid');">Album Id</a>

Better solution would be to use:

  • Telerik Grid which lets you specify custom routes and also offers much more flexibility in rendering your layout
  • or MvcContrib Grid (not sure if this lets you modify header links but definitely offers more flexibility than WebGrid)


回答2:

@MrChief had the idea above about the ugly hack...I put that together. Here is the main code that I used to do this. It does, indeed, hijack the ajax call before it is put on the wire. The key is to modify the URL that is getting sent because the grid will grab that URL from HttpContext.Request.Path. and plug it into the onclick for the anchor element.

I put this into my main common.js and will simply attach a function to capture the ajaxSend event which happens just before the data is sent.

// Used to hijack the sending of all AJAX calls.  Before it sends the call to the server, it checks to see if the 
// active element (the element that prompted the call) is marked with a given class.  If so, then it will perform
// the given operation.  
$(document).ajaxSend(function (event, jqXHR, ajaxOptions) {

    var activeElement = document.activeElement;

    if ($(activeElement).attr('redosorturl') != null) {

        // If this is a sort anchor link from a grid that needs to have the sort link redone, do it here.
        // the code is in the eipGrip.js file.
        if ($(activeElement).attr('redosorturl').toString() == 'redoSortURL') {
            var newURL = RedoGridSortURL(activeElement, ajaxOptions.url.toString());
            ajaxOptions.url = newURL.toString();
        }
    }

    return false;
});

When rendering the page, I have marked the tag in column header that contains the incorrect URL with a class named "redosorturl', so I know when I hijack the ajax call, the operation has to be done on this element. I then call a custom function that gives me the correct URL, then the ajaxOptions.url is then rewritten with that new URL.

I have to pass the activeElement to that rewrite function so I can traverse up the DOM to get the grid information, where I have put data like the controller and action method that is used along with and IDs and other info that I use for the URL. Likewise, I pass in the current url string because the grid will inject a token at the end of the url that I parse off and put on the new url.



回答3:

Your conclusion isn't right. You just need to wrap your webgrid in a Get form:

using (Html.BeginForm("GetUserList", "ThingaMaBob", System.Web.Mvc.FormMethod.Get))
{
 var grid = new WebGrid(
...
));

    Html.Hidden(grid.SortFieldName, grid.SortColumn);
    Html.Hidden(grid.SortDirectionFieldName, grid.SortDirection == SortDirection.Ascending ? "ASC" : "DESC");
}

The hiddens are so that the sort dir and sort field end up in parseable form in the querystring. You end up with urls like localhost/ThingaMaBob/GetUserList?someotherfields=whatever=&sort=city&sortdir=ASC



回答4:

If you remove [HttpPost] attribute and let the route come to the same function. you'll find the Request["page"] value in your method. this will allow you to put a check on Request["Page"] value.