WebApi2 how to pass Json with an array - c#

I have the following Json with array that I am sending it from AngularJS
{id_fleet: 4177, id_fleetfeature: Array[2]}
var dataFeatures = {
id_fleet: $scope.id,
id_fleetfeature: $scope.selectedFeatures
}
$http.put(myUrl + "Fleets/Insert", JSON.stringify(dataFeatures)).then(function () {
Materialize.toast('Features insertadas correctamente', 3000);
$scope.refreshData();
});
Web API Model
public class modelFleetFeatures {
public int id_fleet { get; set; }
public int[] id_fleetfeature { get; set; }
}
Web API Function
[HttpPut]
[Route("api/Fleets/FleetFeature/Update")]
public HttpResponseMessage updateFleetFeature(List<modelFleetFeatures> data)
{
var cnt = 0;
foreach (var item in data)
{
db.sp_Fleet_FleetFeaturesDelete(item.id_fleet);
db.SaveChanges();
}
foreach (var item in data)
{
db.sp_Fleet_FleetFeaturesInsert(item.id_fleet, item.id_fleetfeature[cnt]);
db.SaveChanges();
cnt +=1;
}
return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
}
In the Web API the value of data always gets null

You are sending single object in JSON, so why expecting list of object in API action?
Just expect single object in api Action , you will get that object model in call like :
public HttpResponseMessage updateFleetFeature(modelFleetFeatures data)
{
//do stuff
}
And no need to stringify json object in put request.
$http.put(myUrl + "Fleets/Insert", dataFeatures).then(function () {
Materialize.toast('Features insertadas correctamente', 3000);
$scope.refreshData();
});

Related

Validate nested Json object in custom model binder in .net core

I created a custom model binder in my .NET Core 3.1 API to validate all JSON parameters (by the help of this post How to validate json request body as valid json in asp.net core).Due to security concern I am checking all the incoming request parameter with the actual model properties(entity model) to avoid parameter tempering(adding additional properties while sending the API request). This is working fine for normal json request but if I have a nested json(nested entity model)then it is validating only main properties(inside properties are not validating)
Example:
for non nested entity models the code is working fine, but if it is a nested models like bellow
public class dep
{
public int depId { get; set; }
public string depName { get; set; }
}
public class EmpModel
{
public dep DepDetails { get; set; }
public string empName { get; set; }
}
The code will validate only the main properties like DepDetails, empName but it wont check the inside properties of DepDetails
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); }
var modelName = bindingContext.BinderModelName ?? "XJson";
var modelType = bindingContext.ModelType;
// create a JsonTextReader
var req = bindingContext.HttpContext.Request;
var raw = req.Body;
if (raw == null)
{
bindingContext.ModelState.AddModelError(modelName, "invalid request body stream");
bindingContext.Result = ModelBindingResult.Failed();
return Task.CompletedTask;
}
JsonTextReader reader = new JsonTextReader(new StreamReader(raw));
try
{
var jsonT = (JObject)JToken.Load(reader, this._loadSettings);
JObject reqeJson = JObject.Parse(jsonT.ToString());
var RequestParameters = reqeJson.Properties().ToList();
var actualParam = bindingContext.ModelMetadata.Properties.ToList();
//checking for additional parameters in input
//Here I am checking if any additional property is appended with the data and for the
//above model in both actualParam and RequestParameters I will get only 2 instead of 3
bool flag = true;
foreach (var obj in RequestParameters)
{
if(!actualParam.Any(item => item.Name.ToUpper() == obj.Name.ToUpper())){
flag = false;
break;
}
JObject tmp = JObject.Parse(obj.ToString());
};
if (!flag)
{
bindingContext.ModelState.AddModelError(modelName, "Additional Data is present in Request");
bindingContext.Result = ModelBindingResult.Failed();
return Task.CompletedTask;
}
var o = jsonT.ToObject(modelType);
bindingContext.Result = ModelBindingResult.Success(o);
}
catch (Exception e)
{
bindingContext.ModelState.AddModelError(modelName, e.ToString());
bindingContext.Result = ModelBindingResult.Failed();
}
return Task.CompletedTask;
}
The Real problem is the content of RequestParameters and actualParam is {DepDetails,empName} but I should get as {depId,depName,empName}
If this method is not correct then please help me with some alternatives.

How to directly map an object class from angular 2 to to web api using JSON?

I have a model class I created in angular 2 to track fields. This same class also exists as a model in my webapi project.
export class People {
Name: string;
Phone: string;
Date: date;}
export class Address {
street: string,
zip: string,
}
in my service I send this to my webapi controller
getPeopleData(peopleModel: People, addressmodel: Address)
{
let headers = new headers(...)
data = {
"p": peopleModel,
"a": addressModel
}
let body = JSON.stringify(data);
return this.http.post(url, body, {headers: headers})
.map((response: Response)=> ...
}
finally in my controller
public JArray GetPeopleData([FromBody]JObject models)
{
var modelPeople = models["p"].ToObject<People>();
var modelAddress = models["a"].ToObject<Address>();
}
modelPeople and modeAddress doesn't map. How can I get my model to map directly.
All I get are a bunch of null fields when there is a string of data in the JObject.
EDIT:
I created a container class that holds the objects of People and Address
public class Container
{
public People people {get; set;}
public Address addresss {get; set;}
}
I then passed in the object to the Container and my results are still null
public JArray GetPeopleData([FromBody]Container container)
{
var modelPeople = container.people;
var modelAddress = container.address;
}
both have all values of null.
I dont get it I feel like I am so close but something is missing
Hello it works for me
//This is a Gobal object
result = {
modelPeople: '',
modelAddress: ''
}
constructor( private _http: Http ) {
}
getJsonModel() {
promise = await this._http.get(URL).toPromise().then(
res => {
this.result= res.json();
}
);
}

Ho to pass a Model Object or a Viewbag to Javascript?

I am using asp.net mvc4 with C#. I get the details from Getdeatils() method of student class. This method return an array. Getdetails method also have same fields like studentBO. In the controller I have a method like follows
public ActionResult Index()
{
List<studentBO> list = new List<studentBO>();
Student.GetDetails[] dt = Student.Getdeatils();
for (int i = 0; i < dt.Length; i++)
{
studentBO.name= dt[i].name;
studentBO.studentno= dt[i].studentno;
studentBO.address= dt[i].address;
list1.Add(studentBO);
}
ViewBag.Registrationlist = list1;
return View(list1);
}
studentBO object have 3 fields
public class studentBO
{
public long studentno{ get; set; }
public string name{ get; set; }
public string address{ get; set; }
}
How can I get viewbag or model in my Jquery `$(document).ready(function () {}` function. I want to get every students name. So I have to use foreach loop as well.
You can serialise your item in the ViewBag and write it to the view, so that the Javascript code will be able to read it:
$(document).ready(function() {
var registrationList = #(Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(ViewBag.Registrationlist)));
for (var i = 0; i < registrationList.length; i++) {
var studentno = registrationList[i].studentno;
var name= registrationList[i].name;
var address= registrationList[i].address;
// write some more code to make use of the values
}
});
Use WebAPI to create a service that returns your objects. Then you can use an ajax-call in your Javascript code to fetch the objects.
WebAPI:
public class StudentsController : ApiController
{
IEnumerable<Student.GetDetails> GetDetails()
{
List<studentBO> list = new List<studentBO>();
Student.GetDetails[] dt = Student.Getdeatils();
for (int i = 0; i < dt.Length; i++)
{
studentBO.name= dt[i].name;
studentBO.studentno= dt[i].studentno;
studentBO.address= dt[i].address;
list1.Add(studentBO);
}
return list1;
}
}
Javascript:
$(document).ready(function () {
// Send an AJAX request
$.getJSON("api/students")
.done(function (data) {
// On success, 'data' contains a list of students.
$.each(data, function (key, item) {
//Do something with the student object
});
});
});

AngularJS object is not properly converted into a ViewModel .NET

I have an AngularJS directive which returns me an array with some values, like this below:
The AngularJS code I'm using to generate this object like above is:
//--------------------------
// service...
service.getSelectedOptions = function() {
var options = [];
for (var I = 0; I < service.optionList.length; ++I) {
var availableOption = service.optionList[I];
if (availableOption.selecionado !== '') {
options.push(availableOption);
}
}
return opcoes;
};
//--------------------------
// controller...
var options = [];
var list = OptionsService.getSelectedOptions();
for (var I = 0; I < list.length; ++I) {
var option = list[I];
options.push({ Handle: option.Handle, Selecionado: option.Selecionado });
}
console.log(options);
// Sending the values to backend...
doPost('..../SaveOptions', { options: options }, function (result) { });
Ok, I created a ViewModel class to receive those objects into my controller.
public class OptionsViewModel {
public int Handle { get; set; }
public string Selecionado { get; set; }
}
My controller is declared like this below:
public JsonResult SaveOptions(OptionsViewModel[] options) {
//...
}
The problem is: if I chose 4 options, the array in the backend has 4 options, but the values are not binded to the objects.
Why that? Anyone knows why? Thanks!!
The solution was modify two parameters in the AJAX call:
Set contentType: "application/json";
Use JSON.stringify(parameters) to the parameters.
Thanks!

backbone and mvc

I have a Backbone project where I have the following model that I want to pass on to .NET for database updating.
var myList = Backbone.Model.extend({
// Default attributes for the todo item.
defaults: function () {
return {
Name: "Default name"
};
},
url: "/my/myList",
"sync": mySyncFunction,
// Ensure that each todo created has `title`.
initialize: function () {
if (!this.get("Name")) {
this.set({ "Name": this.defaults.Name });
}
}
});
Using the following for overriding the sync
function mySyncFunction(method, model, options) {
if (method == 'GET') {
options.url = model.url;
}
else if (method == "create") {
options.url = model.url+"Post";
}
else {
options.url = model.url;
}
Backbone.emulateJSON = true
return Backbone.sync(method, model, options);
}
When creating a new item it is using the model.url+"Post" I assumed and the model.get("Name") contains the correct data. The correct section is executed and the entry in the database is created but the Name is empty.
Although when the .NET Controller handles the post the Name no longer contains any data.
My controller code looks like this.
public class myController : Controller
{
public ActionResult myList()
{
List<myCore.myList> l = new List<myCore.myList>();
l = myCore.myList.ListAll();
return Json(l, JsonRequestBehavior.AllowGet);
}
[HttpPost]
public ActionResult myListPost(myCore.myList doc)
{
doc.AccountGuid = Guid.NewGuid();
Boolean created = doc.Create();
return Json(doc);
}
[HttpPut]
public ActionResult myListPut(myCore.myList doc)
{
myCore.myList doc1 = new myCore.myList();
doc1.AccountGuid = Guid.Empty;
doc1.Name = "testPut";
Boolean created = doc1.Create();
return Json(doc1);
}
[HttpDelete]
public ActionResult myListDelete(myCore.myList doc)
{
//DeleteDoc(id);
myCore.myList doc1 = new myCore.myList();
doc1.id = Guid.NewGuid();
doc1.AccountGuid = Guid.Empty;
doc1.Name = "testDelete";
Boolean created = doc1.Create();
return Json(doc1);
}
}
Can anyone tell me what to do to get the model/class data into the controller.
The myList class looks like this.
public class myList
{
Guid _id = Guid.Empty;
String _name = String.Empty;
Guid _accountGuid = Guid.Empty;
public Guid id
{
get { return _id; }
set { _id = value; }
}
public String Name
{
get { return _name; }
set { _name = value; }
}
public Guid AccountGuid
{
get { return _accountGuid; }
set { _accountGuid = value; }
}
}
UPDATE
It now looks like it works after removing Backbone.emulateJSON = true
Although I still cant get my delete part to work. It comes up with a 404 error. Only Post and Get works.
It looks like this in the controller.
[ActionName("myList")]
[HttpDelete]
public ActionResult myListDelete(myCore.myList doc)
{
doc.Name += "-DELETE";
return Json(doc);
}
UPDATE
Figured that one out as well.
ASP.NET Handle PUT/DELETE verbs
Although i can seem to pass any model or paramters along with it on order to delete the correct entry in the database.
Change your defaults to
defaults: {
Name: "Default name"
},

Categories

Resources