This is a migrated thread and some comments may be shown as answers.

Pass additional parameters as a single object to read method does not work

5 Answers 306 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Dan
Top achievements
Rank 1
Iron
Iron
Veteran
Dan asked on 11 Jul 2018, 09:28 AM

I need to send multiple parameters to the read method of a grid. I have grouped the parameters inside of a class since I have used this with success in the past.

However in the telerik context in does not work

Read([DataSourceRequest]DataSourceRequest request, MyFilter filter) I always get filter with its properties null

Read([DataSourceRequest]DataSourceRequest request, string Prop1, string Prop2) it works the properties have the correct values

Does this not work because of the DataSourceRequestAttribute? Do I have to define also an Attribute to retrieve my properties?

 

5 Answers, 1 is accepted

Sort by
0
Viktor Tachev
Telerik team
answered on 13 Jul 2018, 07:10 AM
Hello Dan,


The result from the function that is passed to the Data() method should be JSON. Thus, you can use custom JavaScript to construct the data and stringify it. 


function additionalData(e) {
    return { complexItem: JSON.stringify({ field1: "sample value", field2:"some other value" }) };
}


Then you can parse it on the server using DeserializeObject method.


var jsonData = JsonConvert.DeserializeObject(complexItem);


Give the approach a try and let me know how it works for you.

Regards,
Viktor Tachev
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Dan
Top achievements
Rank 1
Iron
Iron
Veteran
answered on 13 Jul 2018, 07:33 AM

Hi Viktor,

I had to adapt the code to JsonConvert.DeserializeObject<MyFilter>(complexItem) but it works.

Not really the solution I would have wanted. I would still expect the code Read([DataSourceRequest]DataSourceRequest request, MyFilter filter) to work and the deserialization to be done automatically and not manually

Also this is not really an improvement to the solution Read([DataSourceRequest]DataSourceRequest request, string Prop1, string Prop2) except for the fact that indeed if I am going to add new properties I would have to change only the additionalData script and not the controller also.

0
Viktor Tachev
Telerik team
answered on 17 Jul 2018, 02:58 PM
Hello Dan,

If JSON.stringify is not called the data should be deserialized out of the box. Thus, if the data is passed to the server like this


function additionalData(e) {
    return {
        complexItem: {
            FieldName1: "sample value",
            FieldName2: "some other value"
        }
    }
}


and the read action looks like below:

public ActionResult Read([DataSourceRequest]DataSourceRequest request, MyFilter complexItem)


FieldName1 and FieldName2 should be serialized to the server. 

If you are seeing a different behavior please send us a sample project where the issue is replicated so we can examine it locally.


Regards,
Viktor Tachev
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Dan
Top achievements
Rank 1
Iron
Iron
Veteran
answered on 18 Jul 2018, 06:01 AM

Hi Victor,

I have found my cuprit.

I have told you in my question that I was using Read([DataSourceRequest]DataSourceRequest request, MyFilter filter)

Apparently the DataSourceRequest is using "filter" key to send its filters and I assumed since it is a list of filters the key would be called with the plural and not singular.

0
Viktor Tachev
Telerik team
answered on 18 Jul 2018, 10:17 AM
Hi Dan,

I apologize for not explaining that earlier.

Indeed the DataSource has a filter key that contains the filter options. Additionally filter can have filters option that will hold nested filter expression. The names of additional parameters that are sent to the server should not match any reserved words used by the DataSource widget. 


Regards,
Viktor Tachev
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Boardy
Top achievements
Rank 1
Veteran
commented on 12 Oct 2023, 03:43 PM | edited

Hello,

In my (simlar) case I have a treeview. When a node is selected, a grid next to it should be refreshed with the id (Guid) of the selected node. I used an additionalData() function to add the id in the request. In the network tab in the browser, I can see the data is added to the request, but in my controller the parameter is always empty.

Also when I use a different type of parameter (int or string, either nullable or not) the parameter stays empty.

If I break in my controller and inspect Request.Form["regionId"], I can see the data has been received, but the parameter just isn't filled. Of course I could get the data from there, but I prefer not to go down that road.

Is there something that should be done to allow multiple parameters from the body in an action method? Or is there another reason why the parameter is not filled?

For completeness:

Javascript function called when sending the request

function aditionalData() {
  ...
  if (data)
    return { regionId: data.id };
}

Network data (raw)

sort=&page=1&pageSize=50&group=&filter=&regionId=68908fe2-7aef-4f4c-9144-924e4595b959

Action method in controller

public IActionResult GetRiversInRegion([DataSourceRequest] DataSourceRequest request, Guid? regionId)
{
  return Ok();
}

Alexander
Telerik team
commented on 17 Oct 2023, 01:13 PM

Hi Boardy,

The reported behavior is indeed rather unorthodox. I tried further experimenting with an autonomous Grid component that adds a GUID query parameter. Which is supplemented within the request payload:

Where the "regionId" parameter is bound accordingly to the specified endpoint:

Looking at the provided "Network Data", I presume that a "GET" request is done which adds the meta information directly as a query string. Are my suppositions correct?

If this is the case, the ASP.NET Core framework exposes a built-in [FromQuery] Attribute which as mentioned in the documentation - "Specifies that a parameter or property should be bound using the request query string."

Thus, a possible recommendation would be to alter the endpoint as follows:

public IActionResult GetRiversInRegion([DataSourceRequest] DataSourceRequest request, [FromQuery]Guid? regionId)
{
  return Ok();
}

Nevertheless, I am attaching a runnable sample that tackles the aforementioned suggestion. If this does not help, would it be possible for you to try and replicate the reported behavior within the sample application and send it back for further examination?

This will help me get a better overall understanding of the exact setup on your side, as well as enable me to embark on further debugging endeavors. 

Dan
Top achievements
Rank 1
Iron
Iron
Veteran
commented on 17 Oct 2023, 02:51 PM

Hi Alexander,

Just for you to move on define the property RegionId in another class and use that in the action. And you will be able to receive the additional parameter.

Boardy
Top achievements
Rank 1
Veteran
commented on 18 Oct 2023, 07:40 AM | edited

Hi Alexander,

It is set up the default way with the datasource being

@(Html.Kendo().Grid<RiverViewModel>()
    ...
    .DataSource(ds => ds
        .Ajax()
        .Batch(true)
        .PageSize(20)
        .Read(rd => rd.Action("GetRiversInRegion", "Region").Data("additionalData"))
    )
)

so the action is a POST request. The network data I showed, was from the network tab, raw view. In standard view it's something like this:

So the string in my original post was not cut from the URL, but rather the payload of the request.

Alexander
Telerik team
commented on 19 Oct 2023, 03:35 PM

Hi Boardy,

I have further revamped the sample so that it employs batch editing, as well as making a POST request to the specified endpoint. However, the same behavior seems to be perseverant, as the one demonstrated in my previous reply.

Would it be possible for you to try and reproduce the unorthodox binding anomaly within the sample and send it back for more examination?

Boardy
Top achievements
Rank 1
Veteran
commented on 23 Oct 2023, 09:48 AM

Hi Alexander,

The difference with my situation is that I use razor pages instead of mvc controllers. For the grid read actions, I use an apicontroller. I just changed that in the GridController and now the parameter is not automatically parsed.

As you can see I have also added an work-around to show that the inforation is there.

(The whole sample application is too big for me to upload, so you can just overwrite the controller with the attached version.)

Alexander
Telerik team
commented on 25 Oct 2023, 01:42 PM

Hi Boardy,

Thank you for the additional clarifications, I think I now have a better understanding of the reported anomaly at hand.

Generally, The [ApiController] attribute applies an inference rule for action parameters of type IFormFile and IFormFileCollection. The multipart/form-data request content type is inferred for these types. Meaning, that the request's format will be different in comparison to how a conventional controller processes the data.

With that in mind, in order to bind the passed meta field within the boundaries of the action argument, the [FromForm] attribute needs to be utilized instead. For example:

 public ActionResult Orders_Read([DataSourceRequest] DataSourceRequest request, [FromForm]Guid? regionId)
 {
 }
Boardy
Top achievements
Rank 1
Veteran
commented on 25 Oct 2023, 03:02 PM

Hi Alexander,

Thank you very much. That was indeed the case. I was aware of the [FromBody] and [FromUri] attrbutes, but did not realise there are more variants. Now it works as intended.

Tags
Grid
Asked by
Dan
Top achievements
Rank 1
Iron
Iron
Veteran
Answers by
Viktor Tachev
Telerik team
Dan
Top achievements
Rank 1
Iron
Iron
Veteran
Share this question
or