1

I managed to create an ApiController retrieving data from my repositories, and populating a grid in my view through Bootgrid with Ajax. This is an example of request data sent to Api's Action, given by their Docs here (look for POST Body Request tab):

current=1&rowCount=10&sort[sender]=asc&searchPhrase=&id=b0df282a-0d67-40e5-8558-c9e93b7befed

Here is an example URL:

http://localhost/api/SomeController?current=1&rowCount=10&sort%5BName%5D=asc&searchPhrase=&id=b0df282a-0d67-40e5-8558-c9e93b7befed

I created two Helper classes to handle data I must return as response, and sort data (as it's an array):

public class SortData
{
    public string Field { get; set; } // FIeld Name
    public string Type { get; set; } // ASC or DESC
}

public class BootgridResponseData<T> where T: class
{
    public int current { get; set; } // current page
    public int rowCount { get; set; } // rows per page
    public IEnumerable<T> rows { get; set; } // items
    public int total { get; set; } // total rows for whole query
}

Therefore, my action is as follow:

    public BootgridResponseData<SomeViewModel> Get(int current, int rowCount, List<SortData> sort, string searchPhrase, string id)
    {
       // get items and return a bootgrid response data with them...
    }

The method is invoked and all parameters come with data properly, except sort, which is always null.

What kind of parameter should I expect for this? I also tried to put object but it comes null anyway.

Alisson Reinaldo Silva
  • 10,009
  • 5
  • 65
  • 83

4 Answers4

2

After learning a bit more, I saw Bootgrid has a requestHandler setting which allows you to manipulate data sent to server.

I did it in my javascript like this:

var grid = $("#my-grid").bootgrid({
        ajax: true,
        rowCount: 10,
        ajaxSettings: {
            method: "POST",
            cache: true
        },
        requestHandler: function (request) {
            // Scan the original sort object from Bootgrid...
            // and populate an array of "SortData"...
            request.sortItems = [];
            if (request.sort == null)
                return request;
            for (var property in request.sort) {
                if (request.sort.hasOwnProperty(property)) {
                    request.sortItems.push({ Field: property, Type: request.sort[property] });
                }
            }
            return request;
        },
        url: "/api/FooApi"
    });

Then I created my post action in API like this:

public class FooApiController : ApiController
{

    [HttpPost]
    public BootgridResponseData<FooModel> Get(BootgridRequestData model)
    {
        // This would come from some data store, using the request params...
        // I use PagedList to make pagination easier...
        IPagedList<FooModel> itemsPaged = store.GetPagedFoo();

        // Then return the response with data...
        return new BootgridResponseData<FooModel>()
        {
            current = model.current,
            rowCount = model.rowCount,
            rows = itemsPaged,
            total = itemsPaged.TotalItemCount
        };
    }
}

The BootgridResponseData has already been shown in my question. I just added a BootgridRequestData which the following structure:

public class BootgridRequestData
{
    public int current { get; set; }
    public int rowCount { get; set; }
    public string searchPhrase { get; set; }
    public IEnumerable<SortData> sortItems { get; set; }
}

Then I could even use my original SortData helper class:

public class SortData
{
    public string Field { get; set; } // FIeld Name
    public string Type { get; set; } // ASC or DESC
}
Alisson Reinaldo Silva
  • 10,009
  • 5
  • 65
  • 83
1

I've struggled with this as well. You are overthinking it. It's nice to create simple models to handle the post call from jquery-bootgrid, but you can also just use simple parameters in the post method. As for the sort, it looks like a Key-Value pair, but that doesn't serialize properly.

I ended up trying a Dictionary object and it works.

Here is my signature:

[HttpPost]
public async Task<ActionResult> GetActiveDogs(int? current, int? rowCount, 
                Dictionary<string, string> sort, string searchPhrase = null)
Treetopvt
  • 240
  • 4
  • 8
  • Actually I do prefer simple parameters than complex models to bind data, I just didn't know what to use. I thougth a Dictitionary would fit well, by someone told me using Dictionaries as parameters is not a good thing. Anyway I'm gonna try to use, I sincerely don't know why it shouldn't be a good option. If it works, I accept your answer. Thanks for your help! – Alisson Reinaldo Silva Jan 28 '16 at 11:31
  • Unfortunatelly it didn't work for me, I tried with GET and POST requests. I also tried making the parameter a ``KeyValuePair``, but no success. – Alisson Reinaldo Silva Jan 29 '16 at 15:28
  • My application has OData configured which I know provides a different model binder. Perhaps look at configuring OData to see if that helps with passing a Dictionary? Install-Package Microsoft.AspNet.OData Install-Package Microsoft.AspNet.WebApi.OData – Treetopvt Jan 30 '16 at 16:25
1

I had the same problem passing the sort options to my webservice. The Dictionary object did not solve my problem either. To solve it, I created a class holding string properties for each field I wanted to pass through the bootgrid sort options. See code excerpt

class TestSort
{
   public string field1 { get; set; }
   public string field2 { get; set; }
   ...
}

I use this class as the sort options parameter in my webservice. All fields in this class that are referred to by the bootgrid options are set to "ASC" or "DESC". The others remain null.

I added an 'orderBy' property to this class that returns an orderby clause for the fields that are not null.

0

Approch1. consider you have table with columns "col1, col2, col3, ...". you can use:

public ActionType Get(int current, int rowCount, Sort sort, string searchPhrase) {
    //sort.col1 == 'asc' (consider sorted by col1 in ascending order)
}

public class Sort
{
    public string col1 { get; set; }
    public string col2 { get; set; }
    public string col3 { get; set; }
    //... other columns
}

Approach 2. You can use remove you parameters and parse request data manually. i used post here instead of get.

[HttpPost]
public object Post(){
    string jsonContent = Request.Content.ReadAsStringAsync().Result;
    Dictionary<string, string> keyvalues = new Dictionary<string, string>();
    string[] keyvalue_strings = jsonContent.Split('&');
    string sort_column = "";
    string sort_direction = "";
    for (var i = 0; i< keyvalue_strings.Length; i++)
    {
        var a = keyvalue_strings[i].Split('=');
        a[0] = a[0].Replace("%5B", "[").Replace("%5D", "]");
        keyvalues.Add(a[0], (a[1]));
        if (a[0].Contains("sort"))
        {
            sort_column = a[0].Replace("sort[", "").Replace("]", "");
            sort_direction = a[1];
        }
    }
    //now you have keyvalues, sort_column, sort_direction.
    //...
}
yaya
  • 7,675
  • 1
  • 39
  • 38