Why the controller response are setting model field names into lower case? - c#

In my .NET Core project, in the response of all controllers, the object fields are coming in lower case in the first one or two letters of the field name:
{
"iD_PARAM": "foo",
"cD_PROM": "bar",
"txT_OFFICER": "lorem",
"cN_NEW_PARAM": "fubá",
"iD_SITUATION": "XX",
"iD_NEW_USER": "ipsun",
}
It's strange, because the model has all fields in UPPER case:
public partial class MyModel {
public long ID_PARAM { get; set; }
public long CD_PROM { get; set; }
public string TXT_OFFICER { get; set; }
public int CN_NEW_PARAM { get; set; }
public int ID_SITUATION { get; set; }
public int ID_NEW_USER { get; set; }
}
For more detail, this is the controller where I set the values and the response:
[HttpPost("receive")]
public async Task<IActionResult> Get()
{
try
{
MyModel newParam = new MyModel ();
newParam.ID_PARAM = "foo";
newParam.CD_PROM = "foo";
newParam.TXT_OFFICER = "lorem";
newParam.CN_NEW_PARAM = "fubá";
newParam.ID_SITUATION = "XX";
newParam.ID_NEW_USER = "ipsun";
return Ok(newParam);
}
catch (Exception ex)
{
return BadRequest(ex);
}
}

Assuming you are using Newtonsoft Json, if you want your Json properties to be uppercase, try decorating your Model with JsonProperty like this to prevent the Serializer try to infer the property name :
public partial class MyModel {
[JsonProperty("ID_PARAM")]
public long ID_PARAM { get; set; }
[JsonProperty("CD_PROM")]
public long CD_PROM { get; set; }
[JsonProperty("TXT_OFFICER")]
public string TXT_OFFICER { get; set; }
[JsonProperty("CN_NEW_PARAM")]
public int CN_NEW_PARAM { get; set; }
[JsonProperty("ID_SITUATION")]
public int ID_SITUATION { get; set; }
[JsonProperty("ID_NEW_USER")]
public int ID_NEW_USER { get; set; }
}

You should change the ContractResolver, just add below code in startup ConfigurSservices
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
Refer to Lowercase property names from Json() in .Net core

Related

Json conversion conundrum due to mixed type in List

All - I've stumbled into a scenario that's causing me quite a bit of grief. I have a json structure (produced by gateio api) which on the face of it, looks super simple to deserialize into an object. the jsonTickerString looks like the below:
{
"method":"ticker.update",
"params":[
"BTC_USDT",
{
"period":86400,
"open":"46721.06",
"close":"48130.43",
"high":"48758.59",
"low":"46330.3",
"last":"48130.43",
"change":"2.95",
"quoteVolume":"2246.8399550054",
"baseVolume":"106183751.468785134437"
}
],
"id":null
}
However, this is proving to be deceptively funky when trying to push it into an object model. I derived the object model below and thought we were all set to go:
public partial class GateIoTicker
{
[JsonProperty("method")]
public string Method { get; set; }
[JsonProperty("params")]
public List<ParamElement> Params { get; set; }
[JsonProperty("id")]
public object Id { get; set; }
}
public class ParamClass
{
[JsonProperty("period")]
public long Period { get; set; }
[JsonProperty("open")]
public string Open { get; set; }
[JsonProperty("close")]
public string Close { get; set; }
[JsonProperty("high")]
public string High { get; set; }
[JsonProperty("low")]
public string Low { get; set; }
[JsonProperty("last")]
public string Last { get; set; }
[JsonProperty("change")]
public string Change { get; set; }
[JsonProperty("quoteVolume")]
public string QuoteVolume { get; set; }
[JsonProperty("baseVolume")]
public string BaseVolume { get; set; }
}
public partial struct ParamElement
{
public string coinName;
public ParamClass quoteParams;
public static implicit operator ParamElement(ParamClass quoteparams)
{
return new ParamElement { quoteParams = quoteparams };
}
public static implicit operator ParamElement(string coinname)
{
return new ParamElement { coinName = coinname };
}
}
I then set about populating the object using the standard Json.Net approach:
var gateIoTicker = JsonConvert.DeserializeObject<GateIoTicker>(jsonTickerString);
However, although this correctly deserializes the string element in the "params" object, no amount of coersion will bring about a deserialization of the ParamClass object.
Am I missing something very obvious here?? I've spent an inordinate amount of time trying to figure this out and think it's now time to solicit some superior brain power.
Hope this scans as expected...
[Edit] - further to Serge's suggestion, i took his code and added it as a method on my GatIoTicker object. Would have preferred an option that desrializes using attributes, but this works perfectly. Refactored code looks like:
public partial class GateIoTicker
{
[JsonProperty("method")]
public string Method { get; set; }
[JsonProperty("params")]
public List<ParamElement> Params { get; set; }
[JsonProperty("id")]
public object Id { get; set; }
public GateIoTicker FromJson(string json)
{
var jsonObject = JObject.Parse(json);
var pars = jsonObject["params"] as JArray;
var paramElement = new ParamElement();
foreach (var jObject in pars)
{
if (jObject.GetType().Name.ToString() == "JValue") paramElement.ParamName = ((JValue)jObject).ToString();
else
{
paramElement.ParamBody = jObject.ToObject<ParamClass>();
}
}
GateIoTicker gateIoTicker = new GateIoTicker { Params = new List<ParamElement>() };
gateIoTicker.Id = (string)jsonObject["Id"];
gateIoTicker.Method = (string)jsonObject["method"];
gateIoTicker.Params.Add(paramElement);
return gateIoTicker;
}
}
public partial class ParamElement
{
public string ParamName { get; set; }
public ParamClass ParamBody {get; set;}
}
thanks again for the suggestions and nudges. seasons greetings
Try this, it was tested in Visual studio
var jsonObject = JObject.Parse(json);
var pars = jsonObject["params"] as JArray;
var paramElement = new ParamElement();
foreach (var jObject in pars)
{
if (jObject.GetType().Name.ToString() == "JValue") paramElement.ParamName = ((JValue)jObject).ToString();
else
{
paramElement.ParamBody=jObject.ToObject<ParamClass>();
}
}
GateIoTicker gateIoTicker = new GateIoTicker {Params= new List<ParamElement>()};
gateIoTicker.Id= (string) jsonObject["Id"];
gateIoTicker.Method= (string) jsonObject["method"];
gateIoTicker.Params.Add(paramElement);
ParamElement class
public partial class ParamElement
{
public string ParamName { get; set; }
public ParamClass ParamBody {get; set;}
}

Why does deserialized JSON array return null?

I have a string stream returning JSON data from and API that looks like this:
"{\"Recs\":
[
{\"EID\":\"F67_24_6\",\"ReturnPeriod\":\"1\",\"GageStation\":\"NA\"},
{\"EID\":\"T67_24_6\",\"ReturnPeriod\":\"2.37\",\"GageStation\":\"Magueyes Island\"},
{\"EID\":\"R67_24_6\",\"ReturnPeriod\":\"1\",\"GageStation\":\"50147800\"}
]}"
I am trying to deserialize it to return this:
{"Recs":[
{"EID":"F67_24_6","ReturnPeriod":"1","GageStation":"NA"},
{"EID":"T67_24_6","ReturnPeriod":"2.37","GageStation":"Magueyes Island"},
{"EID":"R67_24_6","ReturnPeriod":"1","GageStation":"50147800"}
]}
I am using these public classes to structure the return:
public class New_Events_Dataset
{
public string EID { get; set; }
public string ReturnPeriod { get; set; }
public string GageStation { get; set; }
}
public class NewRootObject
{
public List<New_Events_Dataset> Reqs { get; set; }
}
When I try to apply this later, I basically get a return of {"Reqs":null}. What am I doing wrong here?
var jsonResponse = JsonConvert.DeserializeObject<NewRootObject>(strresult);
string json = new JavaScriptSerializer().Serialize(jsonResponse);
return json;
I think Reqs should be Recs:
public class NewRootObject
{
public List<New_Events_Dataset> Reqs { get; set; }
}
try:
public class NewRootObject
{
public List<New_Events_Dataset> Recs { get; set; }
}
Rename Reqs to Recs and create default constructor of class and instantiate Recs list
public class NewRootObject
{
List<New_Events_Dataset> Recs { get; set; }
public NewRootObject()
{
Recs = new List<New_Events_Dataset>();
}
}

failing to bind string indexed query string parameters

I'm attempting to bind some query string parameters that is indexed by string keys but i can't seem to be getting it to work
here are the values i was trying to bind
search[value]: Exception happ...
search[regex]: false
here is the model i'm trying to bind it with
getLogsAjax(DataTableAjaxPostModel model)
public class DataTableAjaxPostModel
{
public int draw { get; set; }
public int start { get; set; }
public int length { get; set; }
public List<Column> columns { get; set; }
public search search { get; set; }
public List<Order> order { get; set; }
}
public class search
{
public string value { get; set; }
public string regex { get; set; }
}
the rest of the model is being bind correctly except for the search class object, i tripled check that the request contains values for that object, what am i missing here?
p.s. the same code was supposedly working pre .net core
A little more background of the code would be helpful such as the code section that is actually doing the binding however here is a dotnetcore controller example with query parameter binding. Also common practice in C# are class names and fields are both uppercase FYI.
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
public class SampleController : Controller
{
[HttpGet]
[Route("")]
public IActionResult ExampleGet([FromQuery] DataTableAjaxPostModel dataTableAjaxPostModel)
{
// You should be able to debug and see the value here
var result = dataTableAjaxPostModel.search;
return Ok();
}
public class DataTableAjaxPostModel
{
public int draw { get; set; }
public int start { get; set; }
public int length { get; set; }
public List<Column> columns { get; set; }
public search search { get; set; }
public List<Order> order { get; set; }
}
public class search
{
public string value { get; set; }
public string regex { get; set; }
}
}
You don't need to bind each field manually. Using reflection will make it easily.
Aslo, there's no need bind those outer model's properties (DataTableAjaxPostModel's properties) manually. That's because they will be done by the built-in model binder.
Implementation
create a custom binder QueryStringDictSyntaxBinder<TModel>:
internal class QueryStringDictSyntaxBinder<TModel> : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
try
{
var result = Activator.CreateInstance<TModel>();
foreach(var pi in typeof(TModel).GetProperties())
{
var modelName = bindingContext.ModelName;
var qsFieldName = $"{modelName}[{pi.Name}]";
var field= bindingContext.HttpContext.Request.Query[qsFieldName].FirstOrDefault();
if(field != null){
pi.SetValue(result,field);
}
// do nothing if null , or add model binding failure messages if you like
}
bindingContext.Result = ModelBindingResult.Success(result);
}
catch
{
bindingContext.Result = ModelBindingResult.Failed();
}
return Task.CompletedTask;
}
}
And then decorate the search property with a [ModelBinder(typeof(QueryStringDictSyntaxBinder<search>))] :
public class DataTableAjaxPostModel
{
public int draw { get; set; }
public int start { get; set; }
public int length { get; set; }
public List columns { get; set; }
[ModelBinder(typeof(QueryStringDictSyntaxBinder<search>))]
public search search { get; set; }
public List order { get; set; }
}
Test Case:
I test it with the following requests, and it works fine for me:
?draw=1&search[value]=abc&search[regex]=(.*)&
?draw=1&sEarCh[value]=opq&Search[regex]=([^123]*)&
?draw=1&seaRch[value]=rst&Search[regex]=(.*)&
?draw=1&Search[value]=abc&
?draw=1&
seems like no one has an answer for this, so i took a different route and wrote my own custom binder, if a better answer came, ill accept it instead of this one, probably will refactor it later (hahaha IKR!)
public class DTModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
try
{
var result = new DataTableAjaxPostModel();
if (bindingContext.HttpContext.Request.Query.Keys.Contains("draw"))
result.draw = int.Parse(bindingContext.ValueProvider.GetValue("draw").FirstValue);
if (bindingContext.HttpContext.Request.Query.Keys.Contains("search[value]") &&
bindingContext.HttpContext.Request.Query.Keys.Contains("search[regex]"))
result.search = new search()
{
regex = bindingContext.ValueProvider.GetValue("search[regex]").FirstValue,
value = bindingContext.ValueProvider.GetValue("search[value]").FirstValue
};
//...
bindingContext.Result = ModelBindingResult.Success(result);
}
catch
{
bindingContext.Result = ModelBindingResult.Failed();
}
return Task.CompletedTask;
}
}

How to pass parameters to array class in webapi?

I am new to asp.net mvc webapi.I am create one webapi service.In this service I am sending parameter as an array class.
Below is my service :
[AcceptVerbs("GET", "POST")]
public HttpResponseMessage addBusOrder(string UserUniqueID, int PlatFormID,
string DeviceID, int RouteScheduleId,
string JourneyDate, int FromCityid,
int ToCityid, int TyPickUpID,
Contactinfo Contactinfo, passenger[] pass)
{
//done some work here
}
public class Contactinfo
{
public string Name { get; set; }
public string Email { get; set; }
public string Phoneno { get; set; }
public string mobile { get; set; }
}
public class passenger
{
public string passengerName { get; set; }
public string Age { get; set; }
public string Fare { get; set; }
public string Gender { get; set; }
public string Seatno { get; set; }
//public string Seattype { get; set; }
// public bool Isacseat { get; set; }
}
Now how to pass passenger and contactinfo parameters to the above service.
Is there any changes in webapiconfig file?
i want to pass passenger details like this:
passengername="pavan",
age="23",
Gender="M",
passengername="kumar",
Gender="M",
Age="22
It will be much neater if you can create model of your parameter. To pass them from client side, you need to format them using one of data-interchange format. I prefer use JSON provided by Newtonsoft.Json library. Sending process is handled by HttpClient class provided by System.Net.Http namespace. Here is some sample:
Server Side
//Only request with Post Verb that can contain body
[AcceptVerbs("POST")]
public HttpResponseMessage addBusOrder([FromBody]BusOrderModel)
{
//done some work here
}
//You may want to separate model into a class library so that server and client app can share the same model
public class BusOrderModel
{
public string UserUniqueID { get; set; }
public int PlatFormID { get; set; }
public string DeviceID { get; set; }
public int RouteScheduleId { get; set; }
public string JourneyDate { get; set; }
public int FromCityid { get; set; }
public int ToCityid { get; set; }
public int TyPickUpID { get; set; }
public Contactinfo ContactInfo { get; set; }
public passenger[] pass { get; set; }
}
Client Side
var busOrderModel = new BusOrderModel();
var content = new StringContent(JsonConvert.SerializeObject(busOrderModel), Encoding.UTF8, "application/json");
using (var handler = new HttpClientHandler())
{
using (HttpClient client = new HttpClient(handler, true))
{
client.BaseAddress = new Uri("yourdomain");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
return await client.PostAsync(new Uri("yourdomain/controller/addBusOrder"), content);
}
}
Here's how you can do it:
First, since you are passing two objects as parameters we'll need a new class to hold them (because we can only bind one parameter to the request's content):
public class PassengersContact
{
public Passenger[] Passengers { get; set; }
public Contactinfo Contactinfo { get; set; }
}
and now for your controller (this is just a test controller):
[RoutePrefix("api")]
public class DefaultController : ApiController
{
[HttpPost]
// I prefer using attribute routing
[Route("addBusOrder")]
// FromUri means that the parameter comes from the uri of the request
// FromBody means that the parameter comes from body of the request
public IHttpActionResult addBusOrder([FromUri]string userUniqueId,
[FromUri]int platFormId,
[FromUri]string deviceId, [FromUri]int routeScheduleId,
[FromUri]string journeyDate, [FromUri]int fromCityid,
[FromUri]int toCityid, [FromUri]int tyPickUpId,
[FromBody]PassengersContact passengersContact)
{
// Just for testing: I'm returning what was passed as a parameter
return Ok(new
{
UserUniqueID = userUniqueId,
PlatFormID = platFormId,
RouteScheduleId = routeScheduleId,
JourneyDate = journeyDate,
FromCityid = fromCityid,
ToCityid = toCityid,
TyPickUpID = tyPickUpId,
PassengersContact = passengersContact
});
}
}
Your request should look something like this:
POST http://<your server's URL>/api/addBusOrder?userUniqueId=a&platFormId=10&deviceId=b&routeScheduleId=11&journeyDate=c&fromCityid=12&toCityid=13&tyPickUpId=14
Content-Type: application/json
Content-Length: 110
{
"passengers" : [{
"passengerName" : "name",
"age" : 52
/* other fields go here */
}
],
"contactinfo" : {
"name" : "contact info name",
/* other fields go here */
}
}
Notice the api/addBusOrder comes from concatenating the values of the RoutePrefix/Route attributes.

Only return specific properties

I have developed my first API controlled in MVC4 and through the scaffolding I have got it to automatically output a list of items:
// GET api/ItemList
public IEnumerable<ItemOption> GetItemOptions()
{
var itemoptions = db.ItemOptions.Include(i => i.Item);
return itemoptions.AsEnumerable();
}
This shows all the item properties from my model:
public class ItemOption
{
public int ItemOptionId { get; set; }
public bool Active { get; set; }
public string Name { get; set; }
public string test1 { get; set; }
public double PriceNet { get; set; }
}
How can I specify specific fields I wish to be returned? For example, I just want the ItemOptionId, Active and Name to be returned.
I have tried adding additional includes, but this seems to be at an object level.
Try creating a new type to represent the properties you'd like to return:
public class ItemOptionResult
{
public int ItemOptionId { get; set; }
public bool Active { get; set; }
public string Name { get; set; }
}
And then projecting your ItemOption collection, like this:
// GET api/ItemList
public IEnumerable<ItemOptionResult> GetItemOptions()
{`enter code here`
var itemoptions =
db.ItemOptions
.Select(i =>
new ItemOptionResult
{
ItemOptionId = i.ItemOptionId,
Active = i.Active,
Name = i.Name
});
return itemoptions.AsEnumerable();
}
Try this :
var itemoptions = db.ItemOptions.Select(io => new ItemOption()
{
ItemOptionId = io.ItemOptionId,
Active = io.Active ,
Name = io.Name
}
return itemoptions.AsEnumerable();

Categories