ModelBinding complex javascript object to ASP.NET 7.0 - javascript

I am working with an ASP.NET 7.0 razor project and I have tried to bind a complex Javascript object to the .NET model but it fails.
Javascript object:
var myObj = { id1: ["id1 stuff1","id1 stuff2"], id2: ["stuff","blah"] };
.NET object:
Dictionary<string, List<string>>
It fails at binding List values. Keys are bound though:
Here is my code:
var myObj = { id1: ["id1 stuff1","id1 stuff2"], id2: ["stuff","blah"] };
// posting via jQuery:
$.ajax({
method: 'POST',
url: "/index",
headers: { "RequestVerificationToken": "..." },
data: { myObj },
success: function (response) { }
});
My C# looks like this
public IActionResult OnPost(Dictionary<string, List<string>> MyObj)
{
return Page();
}
Not sure how to fix this. I can't change the Javascript object but the C# can be modified to suit the purpose. Any help appreciated.

Related

How to send a list of objects to controller via Ajax using asp net core 3.1?

I am trying to send a list of objects to controller using ajax and asp .net core. My issue is very very simple and there are lots of answers in SO about my issue but none of them solved my issue. I am new at ASP.NET CORE but very experienced at ASP.NET( the normal one).
When debbuging I get a null list of object.
This is my code:
var detalleVenta = new Array();
detalleVenta.length = 0;
$.each($("#tableventa tbody tr"), function () {
detalleVenta.push({
ProductoId: $(this).find('td:eq(6)').html(),
});
});
console.log(detalleVenta);
var datos =
{
// ignore this, i am trying to capture other data.
"Nit": document.getElementById('Nit').value,
"Nombres":document.getElementById('nombres').value,
"NoComprobante":document.getElementById('nocomprobante').value,
"ClienteId":document.getElementById('clienteselect').value,
"Direccion":document.getElementById('direccion').value,
"FormaPago":document.getElementById('selectformapago').value,
// This is the list I want to send to controller
"detalle": detalleVenta,
};
$.ajax(
{
url: '/Venta/GuardarVenta/',
method:"POST",
data: datos,
traditional: true,
success: function(data, state) {
location.reload();
return;
},
error: function(xhr, textStatus, txt) {
alert(xhr.responseText);
return;
}
});
In the console.log(detalleVenta); code I get this:
but when hitting parameters controller, I get this:
Here are my C# code:
public class VentaController : Controller
{
[HttpPost]
public JsonResult GuardarVenta(List<Binderr> detalle, Venta venta)
{
}
}
public class Binderr
{
public string ProductoId {get;set;}
}
The parameter Venta venta captures good the parameters but the list detalle does not. What am I doing wrong?
EDIT: tried public JsonResult GuardarVenta(Binderr[] detalle, Venta venta got same results, list is null in the controller.
Usually the easiest way is to pass the array to the backend in the form of Json.
Here is a simple example:
var detalleVenta =
[
{ id: "1" },
{ id: "2" },
{ id: "3" }
]
$.ajax({
"type": "POST",
"url": '/Venta/GuardarVenta/',
"dataType": "json",
"contentType": "application/json",
"data": JSON.stringify(detalleVenta),
})
Controller(Add [FromBody]):
[HttpPost]
public JsonResult GuardarVenta([FromBody]List<Binderr> detalle)
{
}
Result:

Fancytree passing parameters when loading nodes

How can I pass parameter to .NET web method with fancytree
Public Shared Function ReadNodes(parentId As String) As String
I am trying to send it like this, but it always gets sent as a querystring parameter.
$("#tree").fancytree( {
source: {
url: "Default.aspx/ReadNodes",
data: {parentId: "-1"},
cache: false
}
} )
Can I somehow pass the value to a method as a parameter?
This doesnt work, I keep getting a loading wheel and then a failure. No javascript errors in console.
I have also tried the server method without a parameter, and I get the same behavior. So perhaps I am doing something else wrong.
Your web method must return an array like:
[WebMethod]
public static IEnumerable ReadNodes(int parentId)
{
return new[] {
new { title = string.Format("1. Child of '{0}'", parentId) },
new { title = string.Format("2. Child of '{0}'", parentId) }
// ...
};
}
And then you call the web method like this
$('#tree').fancytree({
source: {
type: 'POST',
url: 'Default.aspx/ReadNodes',
data: '{ parentId: -1 }',
contentType: 'application/json;',
dataType: 'json'
}
});

jQuery.ajax post JSON sent as concatenated string

i am using a common method for all my $.ajax.post operations, and it is encoding the payload differently per use.
for example, if
data: someJSObject
it gets posted as JSON.
however, if i define the object (i also tried putting properties in 'quotes': val)
data: { mgrID: 0, strId: 0, strName: 'Bowie' }
this gets converted to a url encoded string
mgrID=250411&strId=1006575&strName=Bowie
my post function
$.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
url: url,
data: data,
in chrome console, i can see the object recognized as valid json before post.
You are confusing javascript objects and json. If you want to send json, you must give jquery json.
data: { mgrID: 0, strId: 0, strName: 'Bowie' } is not json.
This is json:
data: '{ "mgrID": 0, "strId": 0, "strName": "Bowie" }'
Note how now i'm assigning a string to data rather than an object.
You can convert an object into json using JSON.stringify(theobject)
data: JSON.stringify({ mgrID: 0, strId: 0, strName: 'Bowie' })
try to stringify it like this:
data: JSON.stringify(data)
Looking at your previous posts I assume that you have a ASP.NET / C# background and hence this answer.
In ASP.NET we have something called auto-serialization.
Suppose if you have a class like this
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
and you have a web-service, controller or whatever that has a method like this
public bool AddPerson(Person person)
You could pass the JavaScript object serialized into a json string like this
var DTO = {
person: {
FirstName: "Hugh",
LastName: "Jackman",
Age: 10
}
};
$.ajax({
type: 'POST',
contentType: 'application/json',
dataType: 'json',
url: url,
data: JSON.stringify(DTO)
}).done(function () {
console.log("I passed an object");
});
And when you go to the server-side method AddPerson and put a break-point on it.
Then you will see that the json string has been automatically de-serialized as an object of the Person class.
This way you can also pass an array of persons which you can retrieve as List<Person>
P.S: JSON.stringify is present in all modern browsers. For older ones, use this fallback.
Update: If the server-side method accepts three parameters like this
public bool AddPerson(string firstName, string lastName, int age)
Then change your DTO like this
var DTO = {
firstName: "Hugh",
lastName: "Jackman",
age: 10
};
and use the same AJAX call.
Please read this if you have time. Using complex types to make calling services less… complex
to post "as json" try
data: (tempobj={my: "data",is: "json"})
or
data: {mypost:{my: "data",is: "json"} }
in the second case you can look for the mypost var in your server code.

MVC 4 APIController not receiving POST data

Sure this had been dealt with many times... but.. just cant see what im doing wrong!
This is a simple JS script that Posts data back to ApiController.
function WebCall(url,parameterObject, callBackFunction) {
this.callbackfunction = callBackFunction;
this.parameterObject = parameterObject;
this.url = url;
self = this;
this.GetData = function () {
//self = this;
$.ajax({
//dataType: "json",
type: "POST",
url: self.url,
data: JSON.stringify(self.parameterObject),
contentType: "application/json;charset=utf-8",
success: function (data) {
self.callbackfunction.call(this, data);
},//self.GotData,
error: function (xhRequest, ErrorText, thrownError)
{
alert("error : " + ErrorText)
},
complete: function () {},
})
}
}
The data being sent (parameterObject) is simply
var postData = {
clientId: id
}
The c# code in the controller is :
public class ClientPostObject
{
public string clientId;
}
public class ClientDetailController : ApiController
{
[HttpPost]
public ClientDetailWidgetData GetClient(ClientPostObject clientObject)
{
return new ClientModel().GetClientDetail(clientObject.clientId);
}
}
In Google chrome developer tools, the XHR is showinf 'form Data' as clientId:A0001 - so that looks ok?
No matter what I try (and I'be been through many suggestions on the web), the post data is not there.
Sure its something simple.... Thanks in advance.
Unless you're planning on using a full-on form to submit to this method at some other point, it doesn't really make sense to ask the model binder to attempt to bind to a complex type when you're just using one property. Change your method signature to:
[HttpPost]
public ClientDetailWidgetData GetClient(int clientId) // or whatever type clientId represents
{
return new ClientModel().GetClientDetail(clientId);
}
I'd also recommend adding Glimpse at some point (http://getglimpse.com/) so that you can see how the model binding and/or routing of your app works.
Try to ditch contentType and don't stringify data:
$.ajax({
type: "POST",
url: self.url,
data: self.parameterObject,
success: function (data) {...},
...
});

Jquery post to Action with Dictionary Parameter

I am feeling dejavu, but I cannot find the answer to this:
I have an array of objects that needs to look like this when inspecting a jQ $.post call:
limiter[0].Key
limiter[0].Value
so that it is mapped in the action
public ActionResult SomeAction(Dictionary<Guid, string> dictionary) { }
However, this javascript:
// Some Guid and Some Value
var param = [ { 'Key' : '00000000-0000-00000-000000', 'Value': 'someValue' } ];
$.post('/SomeController/SomeAction/',
{
dictionary: limiter,
otherPostData: data
},
function(data) {
callback(data);
}
)
produces this when inspecting it in firebug:
limiter[0][Key] = someKey // Guid Value
limiter[0][Value] = someValue
This is in jq 1.4.2. I seem to remember some flag you need to set to render json a different way in jQ. Does this ring any bells?
Try like this:
var param = {
'[0].Key': '28fff84a-76ad-4bf6-bc6d-aea4a30869b1',
'[0].Value': 'someValue 1',
'[1].Key': 'd29fdac3-5879-439d-80a8-10fe4bb97b18',
'[1].Value': 'someValue 2',
'otherPostData': 'some other data'
};
$.ajax({
url: '/Home/SomeAction/',
type: 'POST',
data: param,
success: function (data) {
alert(data);
}
});
should map to the following controller action:
public ActionResult SomeAction(Dictionary<Guid, string> dictionary, string otherPostData)
{
...
}
var dict = {}
dict["key1"] = 1
dict["key2"] = 2
dict["key3"] = 3
$.ajax({
type: "POST",
url: "/File/Import",
data: dict,
dataType: "json"
});
public void Import(Dictionary<string, int?> dict)
{
}
just send your obj as dataType: "json"
You can use this flag -
jQuery.ajaxSetting.traditional = true;
To get jQuery to post the data in a different format to the one you are seeing. See this question for further info -
Passing arrays in ajax call using jQuery 1.4
You will see the post param as limiter[0][Key] because jquery serializes the json data before it posts it. This is very well interpreted by the controller action and you get the required input in the action.
You can also use a list of objects and the result will be the same as what you wanted. This is a nice example.
http://www.mikesdotnetting.com/Article/96/Handling-JSON-Arrays-returned-from-ASP.NET-Web-Services-with-jQuery

Categories

Resources