I have a model in C# like this
public class SendEmailModel
{
public List<string> UsersToEmail { get; set; }
public string Subject { get; set; }
public string Message { get; set; }
public bool SendCopy { get; set; }
}
But when I pass the JSON in it does not bind to the List UsersToEmail but everything else works fine.
public JsonResult SendEmail(SendEmailModel sem)
Is there something special that needs to be done to inform the model binding that there is a object in this class that is a List of strings ? Or should it be smart enough to pick this up automatically ?
I figured it out. On the javascript side this piece was added.. once I removed it it works fine..
data: fixedEncodeURI($.param(values)),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
Related
I have a json object like that:
And i want to access the "question" field throught this code-line:
string msg = (json1["data"][0]["question"]).ToString();
But it doesnt work, why?
But it doesnt work, why?
Because you need to look at the json again.
"data" is an object, not an array. As such "[0]" is not valid as it would access the first element of the array. The only array you have in there is the "answers" element. "question" is directly a property of "data".
Prepare a C# Model like below
public class rootClass
{
public bool ok { get; set; }
public data data { get; set; }
}
public class data
{
public string question { get; set; }
public string[] answers { get; set; }
public int id { get; set; }
}
and use JsonConvert(Newtonsoft dll) class to deserialise and access like below
rootClass rootClass = JsonConvert.DeserializeObject<rootClass>(inputJson);
string msg = rootClass.data.question;
I have 2 applications, one which posts data to another. When I run the first application the post method in the controller executes but the model or ObjavaDto (objaveList) can't be found so it's null. When I copy-paste the json from var json into Postman everything works. What am I missing?
var json = new JavaScriptSerializer().Serialize(objaveList[2]);
I used [2] just for simplicity reasons because there are a lot of them
string url = "http://localhost:61837/api/Objave";
string result;
using (var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/json");
result = client.UploadString(url, "POST", json);
}
2nd application Controller
namespace StecajeviInfo.Controllers.Api
{
[Route("api/[controller]")]
public class ObjaveController : Controller
{
[HttpPost]
public void Post([FromBody]ObjavaDto objaveList)
{
}
}
}
public class ObjavaDto
{
public string OznakaSpisa { get; set; }
public string NazivOtpravka { get; set; }
public string NazivStecajnogDuznika { get; set; }
public string PrebivalisteStecajnogDuznika { get; set; }
public string SjedisteStecajnogDuznika { get; set; }
public string OIBStecajnogDuznika { get; set; }
public string OglasSeOdnosiNa { get; set; }
public DateTime DatumObjave { get; set; }
public string OibPrimatelja { get; set; }
public string Dokument { get; set; }
}
Sent data looks like this
{
"OznakaSpisa":"St-6721/2015",
"NazivOtpravka":"Rješenje - otvaranje stečajnog postupka St-6721/2015-7",
"NazivStecajnogDuznika":"RAIN AIR d.o.o.",
"PrebivalisteStecajnogDuznika":"Savska 144/A, 10000, Zagreb",
"SjedisteStecajnogDuznika":"",
"OIBStecajnogDuznika":"37144498637",
"OglasSeOdnosiNa":"Missing Oib",
"DatumObjave":"\/Date(1501106400000)\/",
"OibPrimatelja":"37144498637",
"Dokument":"e-oglasna.pravosudje.hr/sites/default/files/ts-zg-st/…;"
}
Thank you all for your replies, you have been very helpful and gave me an idea how to test. I tested with commenting out properties and I found out it's because of the special characters in Naziv otpravka ("Rješenje" and "stečajnog") which are luckily present only in that property.
I found that this solved the problem https://stackoverflow.com/a/12081747/6231007
client.Headers["Content-Type"] = "application/json; charset=utf-8";
client.UploadDataAsync(new Uri(url), "POST",
Encoding.UTF8.GetBytes(json));
Datetime is problematic. Make it nullable (DateTime?) and test with that. You'll probably get all other properties filled and datetime will stay null. If that's the problem, make sure your client sends datetime format that your model binder understands.
I'm trying to build a model to receive data from a HTTPPOST.
The model is received and populated fine - except for IList<harsta> harequest
It shows as having a count of 1, but having null values against the fields:
My model is:
public class HAR
{
public int api_version { get; set; }
public IList<harsta> harequest { get; set; }
public class harsta
{
public int ta_id { get; set; }
public string partner_id { get; set; }
public string partner_url { get; set; }
}
...
...
}
The Post data for harrequest is (should have 2 entries):
[{"ta_id":97497,"partner_id":"229547","partner_url":"http://partner.com/deeplink/to/229547"},
{"ta_id":97832,"partner_id":"id34234","partner_url":"http://partner.com/deeplink/to/id34234"}]
A screenshot from PostMan shows the form encoded data that is sent to the controller:
Example Request (this is the example provided on the 3rd party website)
POST
http://partner-site.com/api_implementation/ha
BODY
api_version=4
&harequest=[{"ta_id":97497,"partner_id":"229547","partner_url":"http://partner.com/deeplink/to/229547"},{"ta_id":97832,"partner_id":"id34234","partner_url":"http://partner.com/deeplink/to/id34234"}]
&start_date=2013-07-01
...
&query_key=6167a22d1f87d2028bf60a8e5e27afa7_191_13602996000
I'm sure it's not mapping to my model, because of the way I've setup my model here:
public IList<harsta> harequest { get; set; }
public class harsta
{
public int ta_id { get; set; }
public string partner_id { get; set; }
public string partner_url { get; set; }
}
Have I setup the model incorrectly, to receive the JSON data from the harequest field in the POST?
First of all, I'm not exactly comfortable with the embedding of the Harsta class in the Har class. Not good practice separate them.
Secondly, I think your problem actually stems from the fact the property names in the JSON object(s) you are returning are enclosed in quotes. Get rid of the quotes for only the property names.
That is don't do this:
[{"ta_id":97497,"partner_id":"229547","partner_url":"http://partner.com/deeplink/to/229547"},
{"ta_id":97832,"partner_id":"id34234","partner_url":"http://partner.com/deeplink/to/id34234"}]
Do this instead:
[{ta_id:97497,partner_id:"229547",partner_url:"http://partner.com/deeplink/to/229547"},
{ta_id:97832,partner_id:"id34234",partner_url:"http://partner.com/deeplink/to/id34234"}].
There seems to be many questions relating to binding on a DataTable, but none that I could find touch on my exact situation.
I'm currently ajax binding on a list of objects like such:
public class MyObject
{
public string Name { get; set; }
public string Something1{ get; set; }
public string Something2{ get; set; }
public string Something3 { get; set; }
public MyObjectMyObject2 { get; set; }
}
public class MyObject2
{
public string Color { get; set; }
public string Something4 { get; set; }
}
[GridAction]
public ActionResult GetData()
{
var data = QueryDatabaseAndInstantiateAListOfMyObjects();
return View(new GridModel(data));
}
And with a view like such:
<%= Html.Telerik().Grid<MyObject>()
.DataBinding(dataBinding => dataBinding.Ajax().Select("GetData", new { action = "GetData" }))
.Name("Grid1")
.Columns(columns =>
{
columns.Bound(o => o.Name).Title("Name1");
columns.Bound(o => o.MyObject2.Color).Title("Color");
columns.Bound(o => o.Something1).Hidden(true);
columns.Bound(o => o.Something2).Hidden(true);
columns.Bound(o => o.Something3).Hidden(true);
columns.Bound(o => o.MyObject.Something4).Hidden(true);
})
%>
This works great and all as I'm able to sort, group, and all the above.
My situation is I have many properties on MyObject and some edges cases are popping up that are yielding a couple megabytes of response data. The reason being there are many many hidden columns that are situational dependent that a user can right-click to show. The problem is, data for all these extra hidden columns are included in the response data even when they're not used per say. And since the act of grouping, un-grouping, showing and hiding columns fetches for data anyways, why does all the extra data have to come with it?
If I could have only the data returned that is necessary to populate the visible columns plus say a couple that I could mark somehow with a custom attribute, that would immensely help cut back on the size of the returned data.
So I took to converting my list of objects to a DataTable that I could then conditionally add columns + data for and then feed that to the GridModel. This worked well up until trying to group by a column that is in a nested object such as o.MyObject2.Color.
I run into this exception:
Property with specified name: MyObject2.Color cannot be found on type: System.Data.DataRowView
I guess this makes sense, but how do I overcome this? When I use Object Shredder, it sets each property of MyObject loosely typed such as ["Name"] as a string and ["MyObject2"] as a MyObject2. But everything past ["MyObject2"] is strongly typed: (dataRow["MyObject2"] as MyObject2).Color. And this is where is gets over my head.
Is there another way to overcome my initial issue of all that extra data being sent that isn't used? Or, is there any advice with the DataTable bit? I've also tried converting the DataTable to a IEnumerable with no such luck. The serialized Json is quite empty. I've also tried flattening all nested objects such as having datarow["MyObject2.Color"] as string, but this wreaks havok when referencing this column in JavaScript so I had to go with an underscore delimiter ["MyObject2_Color"] but this really screws up binding Columns in the UI. There has to be a way!
I don't see any reason to bring back your full object just to show Color and Something4. Try flattening it out. Something like this where you just assign the values of Color and Something4 to the properties of the model.
public class MyObject
{
public string Name { get; set; }
public string Something1{ get; set; }
public string Something2{ get; set; }
public string Something3 { get; set; }
public string Something4 { get; set; }
public string Color { get; set; }
}
[GridAction]
public ActionResult GetData()
{
var data = QueryDatabaseAndInstantiateAListOfMyObjects();
data.Something4 = MyObject2.Something4;
data.Color = MyObject2.Color;
return View(new GridModel(data));
}
This is the true Answer, but I'm giving credit to Alfalfa for the idea.
I continue along with the DataTable idea, but use getters to expose each nested object property. It's a bit conveluded and brittle, but it works!
public class MyObject
{
public string Name { get; set; }
public string Something1{ get; set; }
public string Something2{ get; set; }
public string Something3 { get; set; }
[ScriptIgnore()]
public MyObjectMyObject2 { get; set; }
public string Color { get { return this.MyObject2.Color; } }
public string Something4 { get { return this.MyObject2.Something4; } }
}
public class MyObject2
{
public string Color { get; set; }
public string Something4 { get; set; }
}
I have a JSON array like this:
"{structChangeList : '[{"structChange":{"id":"Level1.Second","parentId":"Level1.First","date":"2011-01-01"}}]'"
or
"[{"structChangeList":{"id":"Level1.Second","parentId":"Level1.First","date":"2011-01-01"}}]"
and various other variationd which I am trying to pick up with a web method like
[WebMethod]
public string receiveStructureUpdates3(List<StrutureData> structChangeList)
{
return "Hello World";
}
where StructureData is:
[DataContract]
public class StrutureData
{
[DataMember]
public string id { get; set; }
[DataMember]
public string parentId { get; set; }
[DataMember]
public string date { get; set; }
}
It works fine when I try to pick up a non array like:
"{"structChange":{"id":"Level1.Second","parentId":"Level1.First","date":"2011-01-01"}}"
with:
[WebMethod]
public string receiveStructureUpdates2(StrutureData structChange)
{
}
But I can't get the array working. Any ideas?
EDIT:
To use an array/list, change:
"{"structChange":{"id":"Level1.Second","parentId":"Level1.First","date":"2011-01-01"}}"
To
{"structChange": [{"id":"Level1.Second","parentId":"Level1.First","date":"2011-01-01"}]}
Because .Net is looking for structChage, it wants to find that first. Since structChange is a List the value for that key needs to be an array.
This is the correct way to send data to an action in the controller
data: "{someField : [[\"Level1.Second\",\"Level1.First\",\"2011-01-01\"]] }