This is part 2 of a 4-part series on using DataTable
s with WebAPI. Check out the other parts here:
So far, we’ve looked at hooking up DataTable
s to a Web API Controller via a simple GET
request. Is that the best way to make our server side call though? We’ve seen a couple of problems with that approach. Anyone with the know-how could spy on the data as we send it across. If we want to show more columns, we’ll push the URL length towards that maximum. Time for plan B.
Plan B involves a small change to our client code. Instead of making a GET
request, we’ll make a POST
request instead.
If you haven't done so yet, grab the code from the previous article: Making a simple GET Request. Open up the Index
view in Visual Studio (Views/Home/Index.cshtml) and scroll down to the scripts
section. We're changing the AJAX method from GET
(the default) to POST
. It now looks like this:
"ajax": {
"url": "/api/customerSearch",
"method": "POST" },
If we now fire up the page in a browser, we get the old error alert again. If we examine what's happened within Developer Tools, we'll see a 405 error (method not allowed).
This is because our Web API Controller has a Get
method, but needs a Post
method. Let's fix that now. Open up the CustomerSearchController
and change the method name to Post
. You can remove the FromUri
attribute too. Why? Because the data is now coming from the request body rather than the URI. Here's the new method:
public IHttpActionResult Post(SearchRequest request)
{
var allCustomers = JsonConvert.DeserializeObject<CustomerData> (CustomerData);
var response = new CustomerSearchResponse
{
Data = allCustomers.Data,
Draw = request.Draw,
RecordsFiltered = allCustomers.Data.Count,
RecordsTotal = allCustomers.Data.Count
};
return Ok(response);
}
Because we’re using POST
this time, we can take advantage of model binding. We can create a set of classes that mirror the structure we see in that URL. We’ll still use the same SearchRequest
in our Controller. Let’s modify the SearchRequest
a little and add some new classes:
public class SearchRequest
{
public int Draw { get; set; }
public int Start { get; set; }
public int Length { get; set; }
public ColumnRequestItem[] Columns { get; set; }
public OrderRequestItem[] Order { get; set; }
public SearchRequestItem Search { get; set; }
}
public class ColumnRequestItem
{
public string Data { get; set; }
public string Name { get; set; }
public bool Searchable { get; set; }
public bool Orderable { get; set; }
public SearchRequestItem Search { get; set; }
}
public class OrderRequestItem
{
public int Column { get; set; }
public string Dir { get; set; }
}
public class SearchRequestItem
{
public string Value { get; set; }
public bool Regex { get; set; }
}
What’s going on here? Let’s remind ourselves of the URL that we saw in the previous article:
http://localhost:56835/api/customerSearch?draw=1&columns[0][data]=companyName&columns[0][name]=&columns[0][searchable]=true&columns[0][orderable]=true&columns[0][search][value]=&columns[0][search][regex]=false&columns[1][data]=address&columns[1][name]=&columns[1][searchable]=true&columns[1][orderable]=true&columns[1][search][value]=&columns[1][search][regex]=false&columns[2][data]=postcode&columns[2][name]=&columns[2][searchable]=true&columns[2][orderable]=true&columns[2][search][value]=&columns[2][search][regex]=false&columns[3][data]=telephone&columns[3][name]=&columns[3][searchable]=true&columns[3][orderable]=true&columns[3][search][value]=&columns[3][search][regex]=false&order[0][column]=0&order[0][dir]=asc&start=0&length=10&search[value]=&search[regex]=false&_=1479364345110
We can tell that the columns and order items are arrays in the URL. The [0] just after columns or order tells us this. Search, on the other hand, doesn’t have an index. It just has value and regex properties. We can call the classes whatever we like. All the model binder cares about is that we have properties with the names it expects to find.
We need an array called Columns
and an array called Order
. We need an object called Search
and a property on the request called Draw
. If we add anything else, it won’t contain any data. Things will still work, though. Likewise, if we miss out any properties on our classes, we won’t get that data. Things will still work though. Now, we could create a custom model binder for this. I’d rather create the classes manually in this example so we can see what’s going on.
And that's all there is to it. We've added the scaffolding for paging, sorting and searching. In the next article, we'll build on this and add paging, sorting and search capabilities to our table.
View original article