I am trying to create an IEnumerable from an HttpPost request.
The JSON in the body reads as follows:
[{"id":15496,"order":0},{"id":15500,"order":1},{"id":15503,"order":2}]
The post request is like so:
[HttpPost("[action]")]
public IActionResult SendReorderRows([FromBody] IEnumerable<ReorderRow> rows){
foreach(var row in rows){
Debug.WriteLine(row.id);
}
}
The referenced class is here:
public class ReorderRow
{
public int id;
public int order;
}
However when I run this example it gives me the
Object reference not set to an instance of an object
error for "rows".
I'm having difficulty finding a basic way to parse JSON and convert it to an IEnumerable for use in the API. Am I missing something straightforward?
Use an array instead.
[HttpPost("[action]")]
public IActionResult SendReorderRows([FromBody] ReorderRow[] rows) {
foreach(var row in rows){
Debug.WriteLine(row.id);
}
}
It will bind to the JSON array.
You also need public properties in the object model in order for them to be properly populated when binding the objects.
public class ReorderRow {
public int id { get; set; }
public int order { get; set; }
}
Reference Model Binding in ASP.NET Core : How model binding works
Related
I am developing an Asp.Net mvc application. In my application, I need to retrieve json object from remote server. I am using web client for it. But it is giving me error. My scenario is below.
I have this url
http://graph.facebook.com/{fb_id}/picture?width=200&height=200&redirect=false
When I access from browser, it return something like this
So I am trying to retrieve that data as json and then serialize them back. So I builds two classes like below to bind that data.
public class FacebookAvatarResponse
{
[JsonProperty("data")]
public FacebookAvatarData Data { get; set; }
}
public class FacebookAvatarData
{
[JsonProperty("height")]
public int Height { get; set; }
[JsonProperty("width")]
public int Width { get; set; }
[JsonProperty("is_silhouette")]
public bool IsSilhouette { get; set; }
[JsonProperty("url")]
public string Url { get; set; }
}
In controll, I built an action method
[AllowAnonymous]
public JsonResult Test(string avatarDataUrl)
{
using (WebClient webClient = new WebClient())
{
string data = webClient.DownloadString(avatarDataUrl);
return Json(JsonConvert.DeserializeObject<FacebookAvatarResponse>(data),JsonRequestBehavior.AllowGet);
}
}
As you can see I am getting that data as json and then return as action result. But when I request that action method passing correct url as parameter, it is giving me this error.
How can I retrieve JSON data from remote server binding to the specific classes?
Possibly your are not passing JSON to DeserializeObject.
JsonConvert.DeserializeObject takes JSON value.
Check your data should be in json format to deserialize.
Json(JsonConvert.DeserializeObject<FacebookAvatarResponse>(data),
JsonRequestBehavior.AllowGet);
I am sending a Json Array from the client web application to asp.net webapi.
For example,
{
"SurveyId":3423,
"CreatorId":4235,
"GlobalAppId":34,
"AssociateList":[
{"AssociateId":4234},
{"AssociateId":43},
{"AssociateId":23423},
{"AssociateId":432}
],
"IsModelDirty":false,
"SaveMode":null
}
Here Associate List is a JSON Array,
Usually it will automatically serialize to a List<> object.
Using the below code ,i am posting the response to the WebApi
public IEnumerable<Associate> Post(ResponseStatus responseStatus)
{
return this.responsestatusrepository.ResponseStatusCheck(responseStatus);
}
The ResponseStatus class is shown below.
public class ResponseStatus : AppBaseModel
{
public int SurveyId { get; set; }
public int CreatorId { get; set; }
public int GlobalAppId { get; set; }
public List<Associate> AssociateList { get; set; }
}
I have changed the List<> to Collection<> as a part of my code analysis correction.
ie, public Collection<Associate> AssociateList { get; set; }
But it is always getting a null value when we are using collection instead of List. Is there any specific reason for this?
Ok, I think I will have to answer this in an indirect way.
What you are passing on to the server is an array of objects (in JSON format), but once you start processing this in C# the array of objects is now treated as a single c# object. Inside this object, your model expects one of the fields to be a Collection of Associate.
Right, when I work with JSON data similar to whats mentioned in this case - I prefer to use Newtonsofts' JOject.
So here is how I made the C# object with the JSON data you provided:
Used your model:
public class ResponseStatus
{
public int SurveyId { get; set; }
public int CreatorId { get; set; }
public int GlobalAppId { get; set; }
public Collection<Associate> AssociateList { get; set; }
}
public class Associate
{
public int AssociateId { get; set; }
}
Made a routine which takes string (the JSON data), and returns an object of type ResponseStatus:
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
---------------------------------------------------------------------
public static ResponseStatus GetResponseStatusObject(string jsonData)
{
JObject jObject = JObject.Parse(jsonData);
return jObject.ToObject<ResponseStatus>();
}
Now when I call this method and pass on the exact same JSON data which you provided, I get this:
This might not directly solve your problem, but hopefully guide you in the right direction in understanding array/object serialization when working with JavaScript/C#.
Best of luck!
JSON deserialization not working for polymorphic attribute behavior-
Sample code -
--MODEL
public class A
{
public string a_property { get; set; }
}
public class B : A
{
public string b_property { get; set; }
}
public class C
{
public A a { get; set; }
}
--API
public partial class TestController : ApiBaseController
{
[HttpGet]
public IHttpActionResult GetC()
{
return Ok<C>(new C(){a = new B(){a_property="test", b_property ="test1"}});
}
[HttpPost]
public IHttpActionResult SaveC(C c)
{
return Ok<C>(c);
}
}
--Web Route config
Config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects;
Config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
Config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.All;
From UI GetC API is called the object returned is C with attribute a of type B. It does have the type detail i.e. [$type A, assembly name]. When the same JSON is posted from client to call SaveC API the deserialized JSON is of type C but the attribute a is of type A instead of B.
I have searched the web but with no help, what am i missing?
JSON.net deserializer is just respecting your model, if you want specify the heritage level for your entity, you need to create a custom converter or you can work with an interface and just use a jsonconvert attribute.
I'm writing a WCF web service which return data as JSON.
This has been working fine, but I wish to return a list of objects, each of which will contain another list of objects.
This results in no data being sent to the client.
How do I serialize this list of complex objects and return it as JSON.
Thanks.
You can create a custom class and with in the custom class you can create some properties with list datatype and return the list of custom class from service method. the below will code helps you
[OperationContract]
[WebGet(UriTemplate = "Get", ResponseFormat = WebMessageFormat.Json)]
List<StoreAndProductDetails> UpdateStoreProductPriceList();
public class StoreAndProductDetails
{
public StoreAndProductDetails();
public List<PriceFeed> listPriceFeed { get; set; }
public List<ProductFeed> listProductFeed { get; set; }
public List<StoreFeed> listStoreFeed { get; set; }
}
I have an object which I am de-serializing using ToJson<>() method from ServiceStack.Text namespace.
How to omit all the GET only propeties during serialization? Is there any attribute like [Ignore] or something that I can decorate my properties with, so that they can be omitted?
Thanks
ServiceStack's Text serializers follows .NET's DataContract serializer behavior, which means you can ignore data members by using the opt-out [IgnoreDataMember] attribute
public class Poco
{
public int Id { get; set; }
public string Name { get; set; }
[IgnoreDataMember]
public string IsIgnored { get; set; }
}
An opt-in alternative is to decorate every property you want serialized with [DataMember]. The remaining properties aren't serialized, e.g:
[DataContract]
public class Poco
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
public string IsIgnored { get; set; }
}
Finally there's also a non-intrusive option that doesn't require attributes, e.g:
JsConfig<Poco>.ExcludePropertyNames = new [] { "IsIgnored" };
Dynamically specifying properties that should be serialized
ServiceStack's Serializers also supports dynamically controlling serialization by providing conventionally named ShouldSerialize({PropertyName}) methods to indicate whether a property should be serialized or not, e.g:
public class Poco
{
public int Id { get; set; }
public string Name { get; set; }
public string IsIgnored { get; set; }
public bool? ShouldSerialize(string fieldName)
{
return fieldName == "IsIgnored";
}
}
More examples in ConditionalSerializationTests.cs
For nullable members, you also have the ability to set it to null before serializing.
This is particularly useful if you want to create a single view/api model that is re-used for several API calls. The service can touch it up before setting it on the response object.
Example:
public SignInPostResponse Post(SignInPost request)
{
UserAuthentication auth = _userService.SignIn(request.Domain, true, request.Username, request.Password);
// Map domain model ojbect to API model object. These classes are used with several API calls.
var webAuth = Map<WebUserAuthentication>(auth);
// Exmaple: Clear a property that I don't want to return for this API call... for whatever reason.
webAuth.AuthenticationType = null;
var response = new SignInPostResponse { Results = webAuth };
return response;
}
I do wish there was a way to dynamically control the serialization of all members (including non-nullable) on a per endpoint fashion.