i need to share some shipment information in my .NET Core 3.1 API project. I've designed an endpoint which returns a collection of objects which satisfy provided filtering conditions contained in SearchResultsDto object. The working principle of filtering mechanism is simple. On the client side, the user selects a property, and provides some value for it. The user may want to filter the table using one, two, or even more properties. So my controller method needs to take a collection of filters (pairs property-filter value) as a parameter. Here's my method, and Filter class definition:
[HttpGet]
public async Task<ActionResult<SearchResultsDto>> GetShipmentAsync([FromQuery] ICollection<Filter> filters,
[FromQuery] int page,
[FromQuery] int pageCapacity,
[FromQuery] DateTime dateTimeInfimum,
[FromQuery] DateTime dateTimeSupremum,
[FromQuery] bool withPodOnly) =>
Ok(await QueryBus
.SendAsync<GetShipmentQuery, SearchResultsDto>(new GetShipmentQuery
{
Page = page,
PageCapacity = pageCapacity,
DateTimeInfimum = dateTimeInfimum,
DateTimeSupremum = dateTimeSupremum,
WithPodOnly = withPodOnly,
Filters = filters
}));
public class Filter
{
public string PropertyName { get; set; }
public string FilterValue { get; set; }
}
How to correctly pass an array of Filter objects using the query string? Is it good approach to use query string for such a behavior? If not, how should i design my endpoint? How to serialize JavaScript objects, and send it using axios, in a proper way, using GET method?
I've already tried something like that:
https://localhost:44348/api/shipment?filters=[propertyName=materialReleaseReceipt&filterValue=WZ]&page=1&pageCapacity=4&dateTimeInfimum=2012-04-23T18:25:43.511Z&dateTimeSupremum=2012-04-23T18:25:43.511Z&withPodOnly=true
But it doesn't work. Filters collection is not parsed correctly.
If you want to pass the data via query string, you can pass it like below,
https://localhost:44385/weatherforecast?filters[0].Id=1&filters[1].Id=2
Just write the querystring like below:
https://localhost:44348/api/shipment?[0].propertyName=materialReleaseReceipt&[0].filterValue=WZ&page=1&pageCapacity=4&dateTimeInfimum=2012-04-23T18:25:43.511Z&dateTimeSupremum=2012-04-23T18:25:43.511Z&withPodOnly=true
For more details of model binding, you can refer to the doc
Related
I am trying to parse in a list of strings from angular to C# but it is giving me a Unsupported Media Type. Usually I have no difficulty with string types but with other objects it doens't work. I am now thinking about making an object that will contain the string and list but am not sure if that is the best way to go about this.
public GetIncomplete(companyId: number, locationCodes: string[]) {
let params = httpParam.append('locationCodes', JSON.stringify(locationCodes));
return this.http.get<IvwStockTransfers>(`${this.URL}/get-incomplete?companyId=${companyId}`, {
params
});
}
I had to remove it from the input and add
List<string> locationCodes = JsonConvert.DeserializeObject<List<string>>(HttpContext.Request.Query["locationCodes"]);
Setup:
Spring 4.3.5.RELEASE
Tomcat 8.5.11
Maven 4.0.0
Java 1.8
Project Background:
I've a JSP that contains three tables. Two of the tables (titled: "unselected" and "selected") act very much like linked selected elements where they transfer rows between one another. The third table (titled: "predefined") is essentially used to add a pre-selected amount of items from the unselected table to the selected table. What ultimately matters here is that the selected table will contain multiple rows that have data attributes with a number associated.
Since it doesn't seem like there are Spring form tags that could peel the data attribute value from a table row, I have some Javascript that maintains hidden input elements to match the values that are in the selected table. This is in the format of: <input type="hidden" id="selectedNumbers" name="selectedNumbers" value="1111"/>. (Fiddle).
Here are how the class and controller are set up:
Class:
public class MyClass
{
private List<Integer> selectedNumbers;
public MyClass()
{
}
public void setSelectedNumbers(List<Integer> selectedNumbers)
{
this.selectedNumbers = selectedNumbers;
}
public List<Integer> getSelectedNumbers()
{
return selectedNumbers;
}
}
Controller:
#Controller
#SessionAttributes({"attributeOne", "attributeTwo"})
#RequestMapping(value = "/mypage")
public class MyController
{
#ModelAttribute
private MyClass initMyClass()
{
return new MyClass();
}
#RequestMapping(value = "/mytablepage", method = RequestMethod.GET)
public String getMyTablePage(Model model, #ModelAttribute("attributeOne") MyClass myClass)
{
return "mypage.mytablepage";
}
#RequestMapping(value = "/mytablepage", method = RequestMethod.POST)
public String postMyTablePage(Model model, #ModelAttribute("attributeOne") MyClass myClass, BindingResult bindResult)
{
//Validate and check for bind errors.
...
//End Validate and check for bind errors.
return "redirect:nextpage.do";
}
}
The problem is largely that Spring seems to only perform a type of update on list values instead of recreating a list from scratch. This ends up causing remnant values that were removed to persist since there doesn't seem to be a way to have Spring delete removed values.
Here is an example of the scenario:
Add number 1111. [1111]
Add number 2222. [1111, 2222]
Add number 3333. [1111, 2222, 3333]
Add number 4444. [1111, 2222, 3333, 4444]
Continue to the next page. (Model attribute updates).
There were no previous values, so the list is [1111, 2222, 3333, 4444].
Return to the page.
Remove number 3333. [1111, 2222, 4444].
Remove number 1111. [2222, 4444].
Continue to the next page. (Model attribute updates).
We only sent across two values, so it updates the first two values in the list it had prior, resulting in [2222, 4444, 3333, 4444].
Questions:
Is there a way to force Spring to always create a new list or ensure that there are no remnant values that persist?
My current workaround is to never truly delete the values from the list; instead, I essentially null them and have a filter in my controller that compresses the list down by checking for null values and removing them. Is this even sane?
If anything doesn't make sense or doesn't actually reflect what I'm saying, please let me know. There's a lot involved that I've tried to minimize out, so there certainly could be some other factors causing this that I haven't thought of.
I have a situation that I just cannot figure out how to do. I'm trying to add items to a JSON object that was sent from the controller.
Here's my models:
public class Model1
{
public Model2 item {get;set;}
public List<Model2> items {get;set;}
//
And in the page
var jsonData = #Html.Raw(JSON.Encode(Model))
This gives me the basic but empty model. Now in the page I fill in various fields and want to add the items into the model for posting. So:
jsonData.item.field1 = $("#field1").val();
Then I want to add to the list of items, but I cannot find anything that works:
jsonData.items.add(jsonData.item)
doesn't work throws an error.
jsonData.items.push(jsonData.item);
works but every item I add ends up the same. Meaning that when I add the second item there are two in the list but they have the same values. Any help would be appreciated.
As we know, Javascript can be used as OO language and classes and objects can be created on the fly in javascript.
Per my understanding, you are using below code to get class attributes in the JavaScript
var jsonData = #Html.Raw(JSON.Encode(Model))
When this JSON is returned to the client side, it is considered as single object.
So, you can declare a function, acting as class:
function Model2(jsonData ) {
this.name = jsonData.name;
this.discovered = jsonData.discovered;
};
var objModel2_1= new Model2(jsonData);
Now,
you can declare an array to add the objModel2.
var arrModel2=[];
// add new objects
attModel.push(objModel2_1);
Finally,
when you are done, you can use existing jsonData object to fill
i.e.
jsonData.item=objModel2_1;
jsonData.items=attModel;
Hope, this will help you.
I am currently working on a ASP.Net MVC Razor application.
in my controller, I load two dictionaries with data and place them in a ViewModel as follows:
public Dictionary<String, List<String>> EngineerSchedule { get; set; }
public Dictionary<String, List<String>> WeeklySchedule { get; set; }
when in the view, I traverse the dictionaries to retrieve the List objects at every Key, I then change this String List into an Array and send them to a JavaScript function.
In my Js function, I would like to assign the above array to JS variables, when doing so, the JS variables become an array where the index holds the entire array from the function call.
Also, the params become an array of Chars
Any advice to why this happens will be greatly appreciated!
Code in View:
#foreach(var week in Model.WeeklySchedule)
{
var key = week.Key;
var values = week.Value.ToArray();
string[] eng = { };
foreach (var item in Model.EngineerSchedule)
{
if (item.Key == key)
{
eng = item.Value.ToArray();
}
}
#: gatherTimes('#Html.Raw(Json.Encode(key))', '#Html.Raw(Json.Encode(values))', '#Html.Raw(Json.Encode(eng))');
//In here, both values and engs are Array of the correct type and length
}
function gatherTimes(weekKey, values, engs)
{
var week =[];
var eng = [];
week[week.length] = values;
eng[eng.length] = engs;
for(var i = 0; i < engs.length; i++)
{
alert(engs[i]); //Outputs single chars, rather then the string values
alert(eng[i]); //Outputs an array with the length of all the chars from engs, but this array only has one value, which is the entire array from Engs
}
}
One way to inject server side information into the JavaScript portion of your application is "stringifying" the .Net object and calling JSON.Parse on the client side.
If you have the Json.NET nuget package from Newtonsoft you can use the static method JsonConvert.SerializeObject()
to turn almost any C# data structure into a JSON string.
After you place that string of JSON into your view using the templating feature of the Razor view engine, you can store it to a variable like so:
var engineerString = #JsonConvert.SerializeObject(Model.EngineerSchedule);
var dictionary = JSON.parse(engineerString);
As far as I can tell you are actually giving your javascript function strings as arguments since they are wrapped in quotes. Maybe there lies the confusion?
This question is actually continuing/expanding my question here.
I have the model SchoolTestsPerModulePerStudent which is actually the following
public partial class SchoolTestsPerModulePerStudent
{
public long StudentID { get; set; }
public long ModuleID { get; set; }
public System.DateTime TestDate { get; set; }
public int TestResult { get; set; }
}
As I mentioned at the previous question I have this code at a function of a controller
var query = from b in db.SchoolTestsPerModulePerStudent
where b.StudentID.Equals(2)
select b;
return View(query.ToArray());
Well, now, b gets all the SchoolTestsPerModulePerStudent records for the Student with StudentID 2.
The problem I have now, is that I want to split b, in two different arrays, which I want to be used as arrays in javascript at my view.
So now I have two problems:
Is it possible to break my array containing the SchoolTestsPerModulePerStudent records to two different ones that I can return at the view? More specifically, I want the first to contain only the TestDate, while the second to contain only the TestResult. I cannot find any option I can use to create arrays only from a column of an other table...
The second is how I am able to return both these new arrays using one function only? Is it possible? Basically, what I want to avoid, is a second execution of the query (delay), and also the cases where if I execute two queries to get each one of the tables, that it is possible that there are cases where the elements will be returned to be with different order, so the two arrays will not match.
In addition in javascript, at my previous question I got answer that be returned as arrays, they should be returned as JSON like that #Json.Encode(Model). So I can use #Json.Encode(TestDatesArray) and #Json.Encode(TestResultsArray) in my case?
Jim,
By creating another model class you can do this with no problems and selecting the data from your query results to an array. Now I am assuming as you stated you only want the two properties TestDate and TestResult in no particular selection order without any other properties.
Model:
public partial class SchoolTestResultsModel
{
public int[] TestResults { get; set; }
public DateTime[] TestDates { get;set; }
}
Adapted Method:
var query = from b in db.SchoolTestsPerModulePerStudent
where b.StudentID.Equals(2)
select b;
var model = new SchoolTestResultsModel();
model.TestDates = query.Select(x => x.TestDate).ToArray();
model.TestResults = query.Select(x => x.TestResult).ToArray();
return View(model);
Then your JSON Encoding can be
#Json.Encode(Model.TestResults)
#Json.Encode(Model.TestDates)
Now ensure that your view is setup to use the new model.
#model SchoolTestResultsModel